Snap for 4448085 from bb2e798ef4d546dd54cd9e95796403062b860c15 to oc-m3-release

Change-Id: I0aff16fbf430ba5e4dbba83b8e06e4a23b38060a
diff --git a/Android.mk b/Android.mk
index 18468ad..7970f6f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -18,6 +18,7 @@
 
 include $(CLEAR_VARS)
 
+
 LOCAL_MODULE_TAGS := optional
 
 include $(LOCAL_PATH)/version.mk
@@ -28,6 +29,8 @@
 
 LOCAL_PACKAGE_NAME := LiveTv
 
+
+
 # It is required for com.android.providers.tv.permission.ALL_EPG_DATA
 LOCAL_PRIVILEGED_MODULE := true
 
@@ -40,29 +43,40 @@
 
 ifdef TARGET_BUILD_APPS
 LOCAL_RESOURCE_DIR += \
+    $(TOP)/prebuilts/sdk/current/support/compat/res \
     $(TOP)/prebuilts/sdk/current/support/v17/leanback/res \
     $(TOP)/prebuilts/sdk/current/support/v7/recyclerview/res
 else # !TARGET_BUILD_APPS
 LOCAL_RESOURCE_DIR += \
+    $(TOP)/frameworks/support/compat/res \
     $(TOP)/frameworks/support/v17/leanback/res \
     $(TOP)/frameworks/support/v7/recyclerview/res
 endif
+LOCAL_SRC_FILES += \
+    src/com/android/tv/tuner/exoplayer/ffmpeg/IFfmpegDecoder.aidl
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-annotations \
-    android-support-v4 \
+    android-support-compat \
+    android-support-core-ui \
     android-support-v7-palette \
     android-support-v7-recyclerview \
     android-support-v17-leanback \
     icu4j-usbtuner \
     lib-exoplayer \
+    lib-exoplayer-v2 \
+    lib-exoplayer-v2-ext-ffmpeg \
+    prebuilt-support-tv-provider \
     tv-common \
 
-LOCAL_JAVA_LIBRARIES := junit
+
+
+
 
 LOCAL_JAVACFLAGS := -Xlint:deprecation -Xlint:unchecked
 
-LOCAL_AAPT_FLAGS := --auto-add-overlay \
+LOCAL_AAPT_FLAGS += --auto-add-overlay \
+    --extra-packages android.support.compat \
     --extra-packages android.support.v7.recyclerview \
     --extra-packages android.support.v17.leanback \
     --extra-packages com.android.tv.common \
@@ -95,16 +109,19 @@
 
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
+
 #############################################################
 # Pre-built dependency jars
 #############################################################
-
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
     lib-exoplayer:libs/exoplayer.jar \
+    lib-exoplayer-v2:libs/exoplayer_v2.jar \
+    lib-exoplayer-v2-ext-ffmpeg:libs/exoplayer_v2_ext_ffmpeg.jar \
+    prebuilt-support-tv-provider:../../../prebuilts/sdk/current/support/tv-provider/android-support-tv-provider.jar \
 
 
 include $(BUILD_MULTI_PREBUILT)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 1faa2ae..8770301 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,12 +20,14 @@
 
     <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" />
     <uses-permission android:name="android.permission.GLOBAL_SEARCH" tools:ignore="ProtectedPermissions"/>
     <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS" />
+    <uses-permission android:name="android.permission.READ_CONTENT_RATING_SYSTEMS" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_TV_LISTINGS" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
-    <uses-permission android:name="android.permission.MODIFY_PARENTAL_CONTROLS" />
     <uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA" />
     <uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA" />
     <uses-permission android:name="com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA" />
@@ -45,8 +47,16 @@
     <permission android:name="com.android.tv.permission.RECEIVE_INPUT_EVENT"
         android:protectionLevel="signatureOrSystem"
         android:label="@string/permlab_receiveInputEvent"
-        android:description="@string/permdesc_receiveInputEvent" tools:ignore="SignatureOrSystemPermissions"/>
-    <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="23"/>
+        android:description="@string/permdesc_receiveInputEvent"
+        tools:ignore="SignatureOrSystemPermissions"/>
+    <!-- Customizes Live TV with customization packages. -->
+    <permission android:name="com.android.tv.permission.CUSTOMIZE_TV_APP"
+        android:protectionLevel="signatureOrSystem"
+        android:label="@string/permlab_customizeTvApp"
+        android:description="@string/permdesc_customizeTvApp"
+        tools:ignore="SignatureOrSystemPermissions"/>
+
+    <uses-sdk android:targetSdkVersion="26" android:minSdkVersion="23"/>
 
     <application android:label="@string/app_name"
         android:name=".TvApplication"
@@ -113,17 +123,33 @@
             android:launchMode="singleTop"
             android:theme="@style/Theme.Setup.GuidedStep" />
 
-        <activity android:name=".dvr.ui.DvrActivity"
+        <activity android:name=".dvr.ui.browse.DvrBrowseActivity"
             android:configChanges="keyboard|keyboardHidden"
             android:launchMode="singleTask"
-            android:theme="@style/Theme.Leanback.Browse" />
+            android:theme="@style/Theme.Leanback.Browse">
+            <intent-filter>
+                <action android:name="android.media.tv.action.VIEW_RECORDING_SCHEDULES" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:mimeType="vnd.android.cursor.dir/recorded_program" />
+            </intent-filter>
+        </activity>
 
-        <activity android:name=".dvr.DvrPlaybackActivity"
+        <activity android:name=".dvr.ui.playback.DvrPlaybackActivity"
             android:configChanges="keyboard|keyboardHidden|screenSize|smallestScreenSize|screenLayout|orientation"
             android:launchMode="singleTask"
-            android:theme="@style/Theme.Leanback" />
+            android:theme="@style/Theme.Leanback">
+            <intent-filter>
+                <action android:name="android.intent.action.VIEW" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <data android:mimeType="vnd.android.cursor.item/recorded_program" />
+            </intent-filter>
+        </activity>
 
-        <activity android:name=".dvr.ui.DvrDetailsActivity"
+        <activity android:name=".dvr.ui.browse.DvrDetailsActivity"
             android:configChanges="keyboard|keyboardHidden"
             android:theme="@style/Theme.TV.Dvr.Browse.Details" />
 
@@ -138,7 +164,7 @@
         <activity android:name=".dvr.ui.DvrSeriesScheduledDialogActivity"
             android:theme="@style/Theme.TV.dialog.HalfSizedDialog"/>
 
-        <activity android:name=".dvr.ui.DvrSchedulesActivity"
+        <activity android:name=".dvr.ui.list.DvrSchedulesActivity"
             android:configChanges="keyboard|keyboardHidden"
             android:theme="@style/Theme.Leanback.Details" />
 
@@ -151,6 +177,8 @@
 
         <service android:name="com.android.tv.recommendation.NotificationService"
              android:exported="false" />
+        <service android:name=".recommendation.ChannelPreviewUpdater$ChannelPreviewUpdateService"
+             android:permission="android.permission.BIND_JOB_SERVICE" />
 
         <receiver android:name="com.android.tv.receiver.BootCompletedReceiver">
             <intent-filter>
@@ -206,6 +234,13 @@
             <meta-data android:name="android.media.tv.input"
                 android:resource="@xml/ut_tvinputservice" />
         </service>
+        <service android:name=".tuner.exoplayer.ffmpeg.FfmpegDecoderService"
+            android:isolatedProcess="true"
+            android:process="com.android.tv.ffmpeg" >
+            <intent-filter>
+              <action android:name=".tuner.exoplayer.ffmpeg.IFfmpegDecoder" />
+            </intent-filter>
+        </service>
         <provider android:name=".tuner.TunerPreferenceProvider"
             android:authorities="com.android.tv.tuner.preferences"
             android:process="com.android.tv.tuner"
@@ -222,24 +257,30 @@
             </intent-filter>
         </activity>
         <!-- TunerInputController should be the same process with MainActivity to check status of MainActivity -->
-        <receiver android:name=".tuner.TunerInputController"
+        <receiver android:name=".tuner.TunerInputController$IntentReceiver"
             android:exported="false">
             <intent-filter>
                 <action android:name="android.intent.action.BOOT_COMPLETED" />
                 <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
                 <action android:name="android.hardware.usb.action.USB_DEVICE_DETACHED" />
                 <action android:name="com.android.tv.action.APPLICATION_FIRST_LAUNCHED" />
+                <action android:name="com.android.tv.action.NETWORK_TUNER_ATTACHED" />
+                <action android:name="com.android.tv.action.NETWORK_TUNER_DETACHED" />
             </intent-filter>
         </receiver>
 
         <!-- DVR -->
-        <service android:name=".dvr.DvrRecordingService" android:label="@string/dvr_service_name"/>
-        <receiver android:name=".dvr.DvrStartRecordingReceiver"/>
+        <service android:name=".dvr.recorder.DvrRecordingService" android:label="@string/dvr_service_name" />
+        <receiver android:name=".dvr.recorder.DvrStartRecordingReceiver" />
 
         <service android:name=".tuner.tvinput.TunerStorageCleanUpService"
             android:permission="android.permission.BIND_JOB_SERVICE"
             android:process="com.android.tv.tuner"
             android:exported="true" />
 
+        <service android:name=".data.epg.EpgFetcher$EpgFetchService"
+            android:permission="android.permission.BIND_JOB_SERVICE" />
+
+
     </application>
 </manifest>
diff --git a/assets/licenses.html b/assets/licenses.html
deleted file mode 100644
index 000aacf..0000000
--- a/assets/licenses.html
+++ /dev/null
@@ -1,298 +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.
-  -->
-
-<html><head><style> body { font-family: sans-serif; } pre { background-color: #eeeeee; padding: 1em; white-space: pre-wrap; } </style></head><body>
-<!-- START Live Channels licenses -->
-<h3>Notices for files:</h3>
-<ul>
-    <li>protobuf</li>
-</ul>
-<pre>Copyright 2008, Google Inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
-    * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
-    * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
-    * Neither the name of Google Inc. nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Code generated by the Protocol Buffer compiler is owned by the owner
-of the input file used when generating it.  This code is not
-standalone and requires a support library to be linked with it.  This
-support library is itself covered by the above license.
-</pre>
-
-<!-- END Live Channels licenses -->
-<!-- START USB Tuner licenses -->
-<h3>Notices for files:</h3>
-<ul>
-    <li>icu4j</li>
-</ul>
-<pre>Copyright (c) 1995-2013 International Business Machines Corporation and others
-
-All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, and/or sell copies of the
-Software, and to permit persons to whom the Software is furnished to do so,
-provided that the above copyright notice(s) and this permission notice appear
-in all copies of the Software and that both the above copyright notice(s) and
-this permission notice appear in supporting documentation.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
-NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE
-LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY
-DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-Except as contained in this notice, the name of a copyright holder shall not be
-used in advertising or otherwise to promote the sale, use or other dealings in
-this Software without prior written authorization of the copyright holder.
-</pre>
-<h3>Notices for files:</h3>
-<ul>
-    <li>ExoPlayer</li>
-</ul>
-<pre>                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   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.
-</pre>
-<!-- END USB Tuner licenses -->
-
-</body></html>
\ No newline at end of file
diff --git a/assets/whitelist.policy b/assets/whitelist.policy
new file mode 100644
index 0000000..33af781
--- /dev/null
+++ b/assets/whitelist.policy
@@ -0,0 +1,39 @@
+clone: 1
+close: 1
+epoll_pwait: 1
+exit: 1
+faccessat: 1
+fstat64: 1
+fstatfs64: 1
+futex: 1
+getegid32: 1
+geteuid32: 1
+getgid32: 1
+getgroups32: 1
+getpriority: 1
+getsockopt: 1
+gettimeofday: 1
+getuid32: 1
+ioctl: 1
+madvise: 1
+mmap: 1
+mmap2: 1
+mprotect: 1
+munmap: 1
+open: 1
+openat: 1
+pread64: 1
+prctl: 1
+pselect6: 1
+read: 1
+readlinkat: 1
+rt_sigprocmask: 1
+rt_sigtimedwait: 1
+sched_yield: 1
+setpriority: 1
+setsockopt: 1
+set_thread_area: 1
+set_tid_address: 1
+sigaction: 1
+sigaltstack: 1
+write: 1
\ No newline at end of file
diff --git a/common/Android.mk b/common/Android.mk
index bd4d99b..d632597 100644
--- a/common/Android.mk
+++ b/common/Android.mk
@@ -10,17 +10,20 @@
 LOCAL_SDK_VERSION := system_current
 
 LOCAL_RESOURCE_DIR := \
+    $(TOP)/prebuilts/sdk/current/support/compat/res \
     $(TOP)/prebuilts/sdk/current/support/v7/recyclerview/res \
     $(TOP)/prebuilts/sdk/current/support/v17/leanback/res \
     $(LOCAL_PATH)/res \
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
     android-support-annotations \
-    android-support-v4 \
+    android-support-compat \
+    android-support-core-ui \
     android-support-v7-recyclerview \
     android-support-v17-leanback \
 
 LOCAL_AAPT_FLAGS := --auto-add-overlay \
+    --extra-packages android.support.compat \
     --extra-packages android.support.v7.recyclerview \
     --extra-packages android.support.v17.leanback \
 
diff --git a/common/OWNERS b/common/OWNERS
new file mode 100644
index 0000000..4aa5fe5
--- /dev/null
+++ b/common/OWNERS
@@ -0,0 +1,2 @@
+nchalko@google.com
+shubang@google.com
diff --git a/common/res/drawable/setup_selector_background.xml b/common/res/drawable/setup_selector_background.xml
index 7351270..b73c581 100644
--- a/common/res/drawable/setup_selector_background.xml
+++ b/common/res/drawable/setup_selector_background.xml
@@ -17,8 +17,7 @@
 
 <ripple xmlns:android="http://schemas.android.com/apk/res/android"
     android:color="?android:attr/colorControlHighlight">
-    <!-- Note that android:start and android:end is not supported in L platform. -->
-    <item android:id="@android:id/mask" android:left="24dp" android:right="24dp">
+    <item android:id="@android:id/mask">
         <shape>
             <solid android:color="@android:color/white"/>
             <corners android:radius="2dp" />
diff --git a/common/res/layout/fragment_setup_multi_pane.xml b/common/res/layout/fragment_setup_multi_pane.xml
index 45aff13..e3ff8d8 100644
--- a/common/res/layout/fragment_setup_multi_pane.xml
+++ b/common/res/layout/fragment_setup_multi_pane.xml
@@ -40,11 +40,13 @@
         android:clipChildren="false"
         android:clipToPadding="false" />
     <!-- TODO: Use button action list in GuidedStepFragment -->
-    <FrameLayout
+    <LinearLayout
         android:id="@+id/done_button_container"
         android:layout_width="@dimen/setup_done_button_container_width"
         android:layout_height="match_parent"
         android:layout_gravity="end"
+        android:orientation="vertical"
+        android:paddingTop="190dp"
         style="?attr/doneButtonContainerStyle"
         android:transitionGroup="true"
         android:transitionName="buttonDoneTransition">
@@ -54,7 +56,6 @@
             android:layout_height="45dp"
             android:layout_marginStart="24dp"
             android:layout_marginEnd="40dp"
-            android:layout_marginTop="190dp"
             android:elevation="0dp"
             android:focusable="true"
             android:fontFamily="sans-serif-condensed"
@@ -65,5 +66,23 @@
             android:text="@string/action_text_done"
             android:textColor="#EEEEEE"
             android:textSize="14sp" />
-    </FrameLayout>
+        <TextView
+            android:id="@+id/button_skip"
+            android:layout_width="match_parent"
+            android:layout_height="45dp"
+            android:layout_marginStart="24dp"
+            android:layout_marginEnd="40dp"
+            android:layout_marginTop="8dp"
+            android:elevation="0dp"
+            android:focusable="true"
+            android:fontFamily="sans-serif-condensed"
+            android:paddingEnd="12dp"
+            android:paddingStart="12dp"
+            android:background="@drawable/setup_action_button_done"
+            android:gravity="center_vertical|start"
+            android:visibility="gone"
+            android:text="@string/action_text_skip"
+            android:textColor="#EEEEEE"
+            android:textSize="14sp" />
+    </LinearLayout>
 </FrameLayout>
diff --git a/common/res/values-af/strings.xml b/common/res/values-af/strings.xml
index 7a11484..ae7dbb6 100644
--- a/common/res/values-af/strings.xml
+++ b/common/res/values-af/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Klaar"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Slaan oor"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S.<xliff:g id="SEASON_NUMBER">%1$s</xliff:g> Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S.<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S.<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S.<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-am/strings.xml b/common/res/values-am/strings.xml
index 45a1b7c..5c2f096 100644
--- a/common/res/values-am/strings.xml
+++ b/common/res/values-am/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"ተከናውኗል"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"ዝለል"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"ም<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>፦ ክ.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"ክ.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"ም<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>፦ ክፍል <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"ክፍል <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ም<xliff:g id="SEASONNUMBER">%2$s</xliff:g>፦ ክፍል <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ክፍል <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ም<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ክፍል፦ <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ክፍል <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ar/strings.xml b/common/res/values-ar/strings.xml
index bedd137..1cb0daa 100644
--- a/common/res/values-ar/strings.xml
+++ b/common/res/values-ar/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"تم"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"تخطي"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"الموسم <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: الحلقة <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"الحلقة <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"الموسم <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: الحلقة <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"الحلقة <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> الموسم رقم <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: الحلقة رقم <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> الحلقة رقم <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"‏<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;الموسم رقم <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: الحلقة <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"‏<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;الحلقة <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-az/strings.xml b/common/res/values-az-rAZ/strings.xml
similarity index 77%
rename from common/res/values-az/strings.xml
rename to common/res/values-az-rAZ/strings.xml
index c844cd6..ca96c57 100644
--- a/common/res/values-az/strings.xml
+++ b/common/res/values-az-rAZ/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Hazırdır"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Keçin"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Epizod<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Fəsil<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Epizod. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>  &lt;i&gt;Epizod. <xliff:g id="EPISODENUMBER">%2$s</xliff:g> &lt;i&gt;"</string>
 </resources>
diff --git a/common/res/values-bg/strings.xml b/common/res/values-bg/strings.xml
index 264a111..607ad9d 100644
--- a/common/res/values-bg/strings.xml
+++ b/common/res/values-bg/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Пропускане"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Сезон <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: епизод <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Епизод <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Сезон <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Еп. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> – „<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>“"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Еп. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> – „<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>“"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“, сезон <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, епизод <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“, епизод <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“, &lt;i&gt;сез. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, еп. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“, &lt;i&gt;еп. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-bn/strings.xml b/common/res/values-bn-rBD/strings.xml
similarity index 77%
rename from common/res/values-bn/strings.xml
rename to common/res/values-bn-rBD/strings.xml
index 836a62a..73706be 100644
--- a/common/res/values-bn/strings.xml
+++ b/common/res/values-bn-rBD/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"সম্পন্ন"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"এড়িয়ে যান"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"সিজন <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> , পর্ব <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"পর্ব<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"সিঃ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: এপিঃ <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"এপিঃ <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> সিজিন<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: পর্ব <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> পর্ব. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;সিজিন<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: পর্ব <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;পর্ব <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ca/strings.xml b/common/res/values-ca/strings.xml
index 6382648..4ef6c99 100644
--- a/common/res/values-ca/strings.xml
+++ b/common/res/values-ca/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Fet"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Omet"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Temporada <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, episodi <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Episodi <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Temporada <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, episodi <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Episodi <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: temporada <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, episodi <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: episodi <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: &lt;i&gt;temp. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: &lt;i&gt;ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-cs/strings.xml b/common/res/values-cs/strings.xml
index 0be8026..a6aa117 100644
--- a/common/res/values-cs/strings.xml
+++ b/common/res/values-cs/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Hotovo"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Přeskočit"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>E<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"E<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> – <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> – <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-da/strings.xml b/common/res/values-da/strings.xml
index 4685b81..3eeb51d 100644
--- a/common/res/values-da/strings.xml
+++ b/common/res/values-da/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Udført"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Spring over"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, afsn. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Afsn. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Afsnit <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>, <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Afsnit <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Afsn. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> afsn. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Afsn. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Afsn. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-de/strings.xml b/common/res/values-de/strings.xml
index a487ff8..11e8b0d 100644
--- a/common/res/values-de/strings.xml
+++ b/common/res/values-de/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Fertig"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Überspringen"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: F<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Folge <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Staffel <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Folge <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>, <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Folge <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>, <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, Staffel <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Folge <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, Folge <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, &lt;i&gt;Staffel <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Folge <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, &lt;i&gt;Folge <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-el/strings.xml b/common/res/values-el/strings.xml
index dba894c..60a7344 100644
--- a/common/res/values-el/strings.xml
+++ b/common/res/values-el/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Τέλος"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Παράβλεψη"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Σεζ. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Επ.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Επ.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Σεζ.<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Επ. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Επ. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Σεζόν<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Επ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Επ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Επ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Επ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-en-rAU/strings.xml b/common/res/values-en-rAU/strings.xml
index 0ea27ed..94d1c12 100644
--- a/common/res/values-en-rAU/strings.xml
+++ b/common/res/values-en-rAU/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Finished"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Skip"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-en-rGB/strings.xml b/common/res/values-en-rGB/strings.xml
index 0ea27ed..94d1c12 100644
--- a/common/res/values-en-rGB/strings.xml
+++ b/common/res/values-en-rGB/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Finished"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Skip"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-en-rIN/strings.xml b/common/res/values-en-rIN/strings.xml
index 0ea27ed..94d1c12 100644
--- a/common/res/values-en-rIN/strings.xml
+++ b/common/res/values-en-rIN/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Finished"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Skip"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-es-rUS/strings.xml b/common/res/values-es-rUS/strings.xml
index 87c881b..3a15ff3 100644
--- a/common/res/values-es-rUS/strings.xml
+++ b/common/res/values-es-rUS/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Listo"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Omitir"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Temporada <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: episodio <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Episodio <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Temporada <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, episodio <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Episodio <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: T<xliff:g id="SEASONNUMBER">%2$s</xliff:g>, episodio <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: episodio <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Temporada <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Episodio <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Episodio <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-es/strings.xml b/common/res/values-es/strings.xml
index 32536d9..0e7e5ef 100644
--- a/common/res/values-es/strings.xml
+++ b/common/res/values-es/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Listo"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Saltar"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Temporada <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: episodio <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Episodio <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Temporada <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: episodio <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Episodio <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"Temporada <xliff:g id="SEASONNUMBER">%2$s</xliff:g> de <xliff:g id="PROGRAMNAME">%1$s</xliff:g>, episodio <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"Episodio <xliff:g id="EPISODENUMBER">%2$s</xliff:g> de <xliff:g id="PROGRAMNAME">%1$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"Temporada <xliff:g id="SEASONNUMBER">%2$s</xliff:g> de <xliff:g id="PROGRAMNAME">%1$s</xliff:g>: &lt;i&gt;episodio <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"&lt;i&gt;Episodio <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt; de <xliff:g id="PROGRAMNAME">%1$s</xliff:g>"</string>
 </resources>
diff --git a/common/res/values-et/strings.xml b/common/res/values-et-rEE/strings.xml
similarity index 78%
rename from common/res/values-et/strings.xml
rename to common/res/values-et-rEE/strings.xml
index 9052178..baa39d7 100644
--- a/common/res/values-et/strings.xml
+++ b/common/res/values-et-rEE/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Valmis"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Jäta vahele"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. hooaeg: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. jagu"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. jagu"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. hooaeg: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. jagu – <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. jagu – <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – <xliff:g id="SEASONNUMBER">%2$s</xliff:g>. hooaeg, <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. jagu"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. jagu"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g>. h.: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. jagu &lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt; <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. jagu &lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-eu/strings.xml b/common/res/values-eu-rES/strings.xml
similarity index 78%
rename from common/res/values-eu/strings.xml
rename to common/res/values-eu-rES/strings.xml
index d7ab52a..90e82da 100644
--- a/common/res/values-eu/strings.xml
+++ b/common/res/values-eu-rES/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Eginda"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Saltatu"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. denboraldiko <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. atala"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. atala"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. denboraldiko <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. atala: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. atala: <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, <xliff:g id="SEASONNUMBER">%2$s</xliff:g>. denboraldia: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. atala"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. atala"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g>. denboraldia: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. atala&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;<xliff:g id="EPISODENUMBER">%2$s</xliff:g>. atala&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-fa/strings.xml b/common/res/values-fa/strings.xml
index 67e9c4e..55e7c48 100644
--- a/common/res/values-fa/strings.xml
+++ b/common/res/values-fa/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"تمام"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"رد شدن"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"فصل<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: قسمت<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"اپیزود <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"ف.<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ق. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"ق. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> فصل <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: قسمت <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> قسمت <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"‏<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;فصل<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: قسمت <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"‏<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;قسمت <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-fi/strings.xml b/common/res/values-fi/strings.xml
index 8c6b99b..274aeb5 100644
--- a/common/res/values-fi/strings.xml
+++ b/common/res/values-fi/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Valmis"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Ohita"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Kausi <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, jakso <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Jakso <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Kausi <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, jakso <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Jakso <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> kausi <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, jakso <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> jakso <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;K<xliff:g id="SEASONNUMBER">%2$s</xliff:g>, J<xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;J<xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-fr-rCA/strings.xml b/common/res/values-fr-rCA/strings.xml
index ed5678e..4f88b20 100644
--- a/common/res/values-fr-rCA/strings.xml
+++ b/common/res/values-fr-rCA/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Terminé"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Ignorer"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Saison <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, ép. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ép. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Saison <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, épisode <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>, « <xliff:g id="EPISODE_TITLE">%3$s</xliff:g> »"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Épisode <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>, « <xliff:g id="EPISODE_TITLE">%2$s</xliff:g> »"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, saison <xliff:g id="SEASONNUMBER">%2$s</xliff:g> : épisode <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, épisode <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S <xliff:g id="SEASONNUMBER">%2$s</xliff:g> : ép. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ép. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-fr/strings.xml b/common/res/values-fr/strings.xml
index b5b2810..95408bd 100644
--- a/common/res/values-fr/strings.xml
+++ b/common/res/values-fr/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"OK"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Passer"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Saison <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, épisode <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Épisode <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, ép. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> : <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ép. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> : <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – S <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, ép. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – Ép. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – &lt;i&gt; S <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, ép. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – &lt;i&gt;, ép. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-gl/strings.xml b/common/res/values-gl-rES/strings.xml
similarity index 78%
rename from common/res/values-gl/strings.xml
rename to common/res/values-gl-rES/strings.xml
index 356ac56..dfcbdfc 100644
--- a/common/res/values-gl/strings.xml
+++ b/common/res/values-gl-rES/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Feito"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Omitir"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"T <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"T<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> T<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;T<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-gu-rIN/strings.xml b/common/res/values-gu-rIN/strings.xml
new file mode 100644
index 0000000..701977f
--- /dev/null
+++ b/common/res/values-gu-rIN/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ 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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="action_text_done" msgid="298287050387266501">"થઈ ગયું"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"છોડો"</string>
+    <string name="display_episode_number_format" msgid="6040735693510854344">"સિઝન<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: એપિસોડ<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
+    <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"એપિસોડ<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
+    <string name="display_episode_title_format" msgid="5041103178918130554">"સિઝન<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: એપિસોડ <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
+    <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"એપિસોડ<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g><xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;સિઝન<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ઍપિસોડ <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ઍપિસોડ <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
+</resources>
diff --git a/common/res/values-hi/strings.xml b/common/res/values-hi/strings.xml
index 27cae84..7bed8f0 100644
--- a/common/res/values-hi/strings.xml
+++ b/common/res/values-hi/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"हो गया"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"अभी नहीं"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"सीज़न<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: एपिसोड<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"एपिसोड <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"सीज़न<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: एपिसोड <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"एपिसोड <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> सीज़न<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: एपिसोड <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> एपिसोड <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;सीज़न<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: एपिसोड <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;एपिसोड <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-hr/strings.xml b/common/res/values-hr/strings.xml
index 6612778..7fad7d0 100644
--- a/common/res/values-hr/strings.xml
+++ b/common/res/values-hr/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Gotovo"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Preskoči"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="SEASONNUMBER">%2$s</xliff:g>. s.: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. ep."</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. ep."</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-hu/strings.xml b/common/res/values-hu/strings.xml
index 138ad85..7b5867e 100644
--- a/common/res/values-hu/strings.xml
+++ b/common/res/values-hu/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Kész"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Kihagyás"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. évad, <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. rész"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. rész"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. évad, <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. rész: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. rész: <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – <xliff:g id="SEASONNUMBER">%2$s</xliff:g>. évad, <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. epizód"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. epizód"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g>. évad <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. rész&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – &lt;i&gt;<xliff:g id="EPISODENUMBER">%2$s</xliff:g>. rész&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-hy/strings.xml b/common/res/values-hy-rAM/strings.xml
similarity index 78%
rename from common/res/values-hy/strings.xml
rename to common/res/values-hy-rAM/strings.xml
index aaa7470..ed13be2 100644
--- a/common/res/values-hy/strings.xml
+++ b/common/res/values-hy-rAM/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Պատրաստ է"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Բաց թողնել"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Ե <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>՝ դրվ. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Դրվ. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Ե<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>՝ դրվ. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Դրվ. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ե<xliff:g id="SEASONNUMBER">%2$s</xliff:g>՝ Դրվ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Դրվ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-in/strings.xml b/common/res/values-in/strings.xml
index da4b820..89f4d53 100644
--- a/common/res/values-in/strings.xml
+++ b/common/res/values-in/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Selesai"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Lewati"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-is/strings.xml b/common/res/values-is-rIS/strings.xml
similarity index 78%
rename from common/res/values-is/strings.xml
rename to common/res/values-is-rIS/strings.xml
index 4752940..d68d825 100644
--- a/common/res/values-is/strings.xml
+++ b/common/res/values-is-rIS/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Lokið"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Sleppa"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S.<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Þ.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. þáttur"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S.<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Þ. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Þ. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S.<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Þ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Þ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Þ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Þ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-it/strings.xml b/common/res/values-it/strings.xml
index f61e02f..137d545 100644
--- a/common/res/values-it/strings.xml
+++ b/common/res/values-it/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Fine"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Ignora"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Stagione <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, puntata <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Stag. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: punt. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Punt. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Stag. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: punt. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Punt. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Stag. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: punt. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Punt. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-iw/strings.xml b/common/res/values-iw/strings.xml
index 7ad220a..fdc75ce 100644
--- a/common/res/values-iw/strings.xml
+++ b/common/res/values-iw/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"סיום"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"דלג"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"עונה <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: פרק <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"פרק <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"עונה<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: פרק <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"פרק <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> עונה <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: פרק <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> פרק <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"‏<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;עונה <xliff:g id="SEASONNUMBER">%2$s</xliff:g> פרק <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"‏<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;פרק <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ja/strings.xml b/common/res/values-ja/strings.xml
index 682fd0d..e0aa93b 100644
--- a/common/res/values-ja/strings.xml
+++ b/common/res/values-ja/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"完了"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"スキップ"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"シーズン <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: エピソード <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"エピソード <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"シーズン <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: エピソード <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>「<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>」"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"エピソード <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>「<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>」"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>、シーズン <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: エピソード <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>、エピソード <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ka/strings.xml b/common/res/values-ka-rGE/strings.xml
similarity index 77%
rename from common/res/values-ka/strings.xml
rename to common/res/values-ka-rGE/strings.xml
index 3c7062f..f930c02 100644
--- a/common/res/values-ka/strings.xml
+++ b/common/res/values-ka-rGE/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"მზადაა"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"გამოტოვება"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"სეზ. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ეპ. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"ეპ. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"სეზ. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, ეპ. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> — <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"ეპ. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> — <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: სეზ. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, ეპ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: სეზ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;სეზ.<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ეპიზ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ეპიზ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-kk/strings.xml b/common/res/values-kk-rKZ/strings.xml
similarity index 77%
rename from common/res/values-kk/strings.xml
rename to common/res/values-kk-rKZ/strings.xml
index 12de7d3..2aca092 100644
--- a/common/res/values-kk/strings.xml
+++ b/common/res/values-kk-rKZ/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Орындалды"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Өткізіп жіберу"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>-маусым, <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>-серия"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>-серия"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>-маусым: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>-серия, \"<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>\""</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>-серия, \"<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>\""</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, <xliff:g id="SEASONNUMBER">%2$s</xliff:g>-маусым, <xliff:g id="EPISODENUMBER">%3$s</xliff:g>-серия"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, <xliff:g id="EPISODENUMBER">%2$s</xliff:g>-серия"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g>-маусым: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>-серия&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, &lt;i&gt;<xliff:g id="EPISODENUMBER">%2$s</xliff:g>-серия&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-km/strings.xml b/common/res/values-km-rKH/strings.xml
similarity index 77%
rename from common/res/values-km/strings.xml
rename to common/res/values-km-rKH/strings.xml
index b835389..252bd37 100644
--- a/common/res/values-km/strings.xml
+++ b/common/res/values-km-rKH/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"រួចរាល់"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"រំលង"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"រដូវកាល<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>៖ ភាគ<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"ភាគ៖ <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"រដូវកាលទី <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>៖ វគ្គ <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"វគ្គ <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> រដូវ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>៖ ភាគ <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ភាគ <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;រដូវកាល​ទី <xliff:g id="SEASONNUMBER">%2$s</xliff:g>៖ ភាគ​ទី <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ភាគ​ទី <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-kn/strings.xml b/common/res/values-kn-rIN/strings.xml
similarity index 77%
rename from common/res/values-kn/strings.xml
rename to common/res/values-kn-rIN/strings.xml
index 7cb096b..6cfb5ca 100644
--- a/common/res/values-kn/strings.xml
+++ b/common/res/values-kn-rIN/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"ಮುಗಿದಿದೆ"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"ಸ್ಕಿಪ್‌ ಮಾಡಿ"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"ಕಾಲ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>ಭಾಗ<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"ಭಾಗ<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"ಸೀ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ಸಂ. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"ಸಂ. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ಸೀ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ಸಂ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ಸಂ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ಸೀ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ಸಂ. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ಸಂ. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ko/strings.xml b/common/res/values-ko/strings.xml
index 923831f..fe8a5c2 100644
--- a/common/res/values-ko/strings.xml
+++ b/common/res/values-ko/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"완료"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"건너뛰기"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"시즌 <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: 에피소드 <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"에피소드 <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"시즌 <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: 에피소드 <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> \'<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>\'"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"에피소드 <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> \'<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>\'"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> 시즌 <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: 에피소드 <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> 에피소드 <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;시즌 <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, 에피소드 <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;에피소드 <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ky/strings.xml b/common/res/values-ky-rKG/strings.xml
similarity index 78%
rename from common/res/values-ky/strings.xml
rename to common/res/values-ky-rKG/strings.xml
index 8bdfadd..b5b804d 100644
--- a/common/res/values-ky/strings.xml
+++ b/common/res/values-ky-rKG/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Бүттү"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Өткөрүп жиберүү"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>-мезгил: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>-серия"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>-серия"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"С<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g> <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>-серия"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_TITLE">%2$s</xliff:g> <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>-серия"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>-эпизод"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="EPISODENUMBER">%2$s</xliff:g>-эпизод"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;М<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: С. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;С. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-lo/strings.xml b/common/res/values-lo-rLA/strings.xml
similarity index 78%
rename from common/res/values-lo/strings.xml
rename to common/res/values-lo-rLA/strings.xml
index a6dad51..c7ac4e2 100644
--- a/common/res/values-lo/strings.xml
+++ b/common/res/values-lo-rLA/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"ສຳເລັດແລ້ວ"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"ຂ້າມ"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-lt/strings.xml b/common/res/values-lt/strings.xml
index 6d6c0ee..2a38d45 100644
--- a/common/res/values-lt/strings.xml
+++ b/common/res/values-lt/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Atlikta"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Praleisti"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g> sezonas: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> serija"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> serija"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g> sezonas: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> serija „<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>“"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> serija „<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>“"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"Programos „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ <xliff:g id="SEASONNUMBER">%2$s</xliff:g> sezonas: <xliff:g id="EPISODENUMBER">%3$s</xliff:g> serija"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"Programos „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ <xliff:g id="EPISODENUMBER">%2$s</xliff:g> serija"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"Programos „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g> sezonas: <xliff:g id="EPISODENUMBER">%3$s</xliff:g> serija&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"Programos „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ &lt;i&gt;<xliff:g id="EPISODENUMBER">%2$s</xliff:g> serija&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-lv/strings.xml b/common/res/values-lv/strings.xml
index f0366a4..473b69f 100644
--- a/common/res/values-lv/strings.xml
+++ b/common/res/values-lv/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Gatavs"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Izlaist"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. sez., <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. sēr."</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. sēr."</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. sezona: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. sērija “<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>”"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. sērija “<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>”"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: <xliff:g id="SEASONNUMBER">%2$s</xliff:g>. sezona, <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. sērija"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. sērija"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g>. sezona, <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. sērija&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>: &lt;i&gt;<xliff:g id="EPISODENUMBER">%2$s</xliff:g>. sērija&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-mk/strings.xml b/common/res/values-mk-rMK/strings.xml
similarity index 77%
rename from common/res/values-mk/strings.xml
rename to common/res/values-mk-rMK/strings.xml
index 73045d3..80603a1 100644
--- a/common/res/values-mk/strings.xml
+++ b/common/res/values-mk-rMK/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Прескокни"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Сез.<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Еп.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Еп.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Сез. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Еп. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Еп. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Сез.<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Еп.. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Еп. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Сез.<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Еп. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Еп. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ml/strings.xml b/common/res/values-ml-rIN/strings.xml
similarity index 77%
rename from common/res/values-ml/strings.xml
rename to common/res/values-ml-rIN/strings.xml
index 0772768..abe8ded 100644
--- a/common/res/values-ml/strings.xml
+++ b/common/res/values-ml-rIN/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"പൂർത്തിയായി"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"ഒഴിവാക്കുക"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"സീസൺ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: എപ്പി.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"എപ്പി.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"സീസൺ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: എപ്പിസോഡ് <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"എപ്പിസോഡ് <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> സീരിയൽ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: എപ്പിസോഡ് <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> എപ്പിസോഡ് <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: എപ്പി. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;എപ്പി. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-mn/strings.xml b/common/res/values-mn-rMN/strings.xml
similarity index 78%
rename from common/res/values-mn/strings.xml
rename to common/res/values-mn-rMN/strings.xml
index ff1552e..aec6c26 100644
--- a/common/res/values-mn/strings.xml
+++ b/common/res/values-mn-rMN/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Дууссан"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Алгасах"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Бүлэг<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Цуврал.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Анги.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Бүлэг<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Анги. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Анги. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Бүлэг<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Анги. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Анги. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Анги <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Анги <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-mr/strings.xml b/common/res/values-mr-rIN/strings.xml
similarity index 78%
rename from common/res/values-mr/strings.xml
rename to common/res/values-mr-rIN/strings.xml
index adc669a..1084c7f 100644
--- a/common/res/values-mr/strings.xml
+++ b/common/res/values-mr-rIN/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"पूर्ण झाले"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"वगळा"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"हंगाम<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: भाग<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"भाग<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"हंगाम<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: भाग. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"भाग. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> सत्र<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: भाग <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> भाग <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: भाग <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;भाग <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ms/strings.xml b/common/res/values-ms-rMY/strings.xml
similarity index 78%
rename from common/res/values-ms/strings.xml
rename to common/res/values-ms-rMY/strings.xml
index 06eb617..1434368 100644
--- a/common/res/values-ms/strings.xml
+++ b/common/res/values-ms-rMY/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Selesai"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Langkau"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"M<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"M<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;M<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-my/strings.xml b/common/res/values-my-rMM/strings.xml
similarity index 77%
rename from common/res/values-my/strings.xml
rename to common/res/values-my-rMM/strings.xml
index 977c431..0e9b43c 100644
--- a/common/res/values-my/strings.xml
+++ b/common/res/values-my-rMM/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"ပြီးပါပြီ"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"ကျော်ရန်"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"အတွဲ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>− အပိုင်း<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"အပိုင်း <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"အတွဲ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>− အပိုင်း <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"အပိုင်း <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> အတွဲ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>− အပိုင်း <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> အပိုင်း <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;အတွဲ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: အပိုင်း <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;အပိုင်း <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-nb/strings.xml b/common/res/values-nb/strings.xml
index 8344a76..61d3607 100644
--- a/common/res/values-nb/strings.xml
+++ b/common/res/values-nb/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Ferdig"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Hopp over"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Sesong <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> episode <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Episode <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Sesong <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: episode <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> – <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Episode <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> – <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Sesong <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Episode <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Episode <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Episode <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Episode <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ne/strings.xml b/common/res/values-ne-rNP/strings.xml
similarity index 77%
rename from common/res/values-ne/strings.xml
rename to common/res/values-ne-rNP/strings.xml
index 4f3d24c..064fc63 100644
--- a/common/res/values-ne/strings.xml
+++ b/common/res/values-ne-rNP/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"सम्पन्न भयो"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"छाड्नुहोस्"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"सिजन <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: एपिसोड <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"एपिसोड <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"सिजन <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: एपिसोड <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"एपिसोड <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> सिजन <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: एपिसोड <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> एपिसोड <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: एपिसोड <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;एपिसोड <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-nl/strings.xml b/common/res/values-nl/strings.xml
index 4e5a101..3b60161 100644
--- a/common/res/values-nl/strings.xml
+++ b/common/res/values-nl/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Gereed"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Overslaan"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> afl. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Afl. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: afl. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Afl. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Afl. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Afl. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>, A<xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;A <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-pa-rIN/strings.xml b/common/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000..c32ca9b
--- /dev/null
+++ b/common/res/values-pa-rIN/strings.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ 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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="action_text_done" msgid="298287050387266501">"ਹੋ ਗਿਆ"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"ਛੱਡੋ"</string>
+    <string name="display_episode_number_format" msgid="6040735693510854344">"ਸੀਜ਼ਨ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ਐਪੀਸੋਡ<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
+    <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"ਐਪੀਸੋਡ<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
+    <string name="display_episode_title_format" msgid="5041103178918130554">"ਸੀਜ਼ਨ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ਐਪੀਸੋਡ <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
+    <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"ਐਪੀਸੋਡ <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ਐਪੀਸੋਡ <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ਐਪੀਸੋਡ <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
+</resources>
diff --git a/common/res/values-pl/strings.xml b/common/res/values-pl/strings.xml
index 5161e3b..baa6a78 100644
--- a/common/res/values-pl/strings.xml
+++ b/common/res/values-pl/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Gotowe"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Pomiń"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Sez. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: odc. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Odc. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Sez. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, odc. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Odc. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – sez. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, odc. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, odc. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;sez. <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: odc. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;odc. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-pt-rPT/strings.xml b/common/res/values-pt-rPT/strings.xml
index badaae2..9d22b24 100644
--- a/common/res/values-pt-rPT/strings.xml
+++ b/common/res/values-pt-rPT/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Concluído"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Ignorar"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"T. <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"T<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> T<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;T<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-pt/strings.xml b/common/res/values-pt/strings.xml
index 0fc3e09..e5aed96 100644
--- a/common/res/values-pt/strings.xml
+++ b/common/res/values-pt/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Concluído"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Pular"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"T<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"T<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> T<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;T <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ro/strings.xml b/common/res/values-ro/strings.xml
index ae6fc49..370c71d 100644
--- a/common/res/values-ro/strings.xml
+++ b/common/res/values-ro/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Terminat"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Omiteți"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Sezonul <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, episodul <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Episodul <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Sezonul <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, episodul <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Episodul <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>: <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, sezonul <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, episodul <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, episodul <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, &lt;i&gt;sezonul <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, episodul <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, &lt;i&gt;episodul <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ru/strings.xml b/common/res/values-ru/strings.xml
index 53c341a..afdbcd5 100644
--- a/common/res/values-ru/strings.xml
+++ b/common/res/values-ru/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Пропустить"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Сезон <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, серия <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Серия <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Сезон <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: серия <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>, \"<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>\""</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Серия <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>, \"<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>\""</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, сезон <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, серия <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, серия <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;сезон <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, серия <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;серия <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-si/strings.xml b/common/res/values-si-rLK/strings.xml
similarity index 77%
rename from common/res/values-si/strings.xml
rename to common/res/values-si-rLK/strings.xml
index 85fc1f9..59d85a6 100644
--- a/common/res/values-si/strings.xml
+++ b/common/res/values-si-rLK/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"නිමයි"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"මඟ හරින්න"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"වාරය<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>කථාංගය<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"කථාංගය <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"වාරය<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: කථාංගය <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"කථාංගය <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> වාරය<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: කථාංගය. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> කථාංගය. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;වා<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: කථාංග. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;කථාංග. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-sk/strings.xml b/common/res/values-sk/strings.xml
index 1d1a673..4d6df3c 100644
--- a/common/res/values-sk/strings.xml
+++ b/common/res/values-sk/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Hotovo"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Preskočiť"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"E<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> – <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> – <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="SEASONNUMBER">%2$s</xliff:g>. sezóna: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. epizóda"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. epizóda"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-sl/strings.xml b/common/res/values-sl/strings.xml
index 26ec614..603d12d 100644
--- a/common/res/values-sl/strings.xml
+++ b/common/res/values-sl/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Končano"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Preskoči"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. sezona: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. epizoda"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. epizoda"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. sezona – <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. epizoda: <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. epizoda: <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – <xliff:g id="SEASONNUMBER">%2$s</xliff:g>. sezona: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. epizoda"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> – <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. epizoda"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g>. sezona: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>.epizoda&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;<xliff:g id="EPISODENUMBER">%2$s</xliff:g>.epizoda&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-lo/strings.xml b/common/res/values-sq-rAL/strings.xml
similarity index 77%
copy from common/res/values-lo/strings.xml
copy to common/res/values-sq-rAL/strings.xml
index a6dad51..ac18898 100644
--- a/common/res/values-lo/strings.xml
+++ b/common/res/values-sq-rAL/strings.xml
@@ -17,11 +17,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="action_text_done" msgid="298287050387266501">"ສຳເລັດແລ້ວ"</string>
+    <string name="action_text_done" msgid="298287050387266501">"U krye"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Kapërce"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-sr/strings.xml b/common/res/values-sr/strings.xml
index ef7f9ee..b64eb7f 100644
--- a/common/res/values-sr/strings.xml
+++ b/common/res/values-sr/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Прескочи"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Серијал: <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Епизода: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. епизода"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>. серијал: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. епизода, <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. епизода, <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="SEASONNUMBER">%2$s</xliff:g>. серијал: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. епизода"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. епизода"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g>. серијал: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. епизода&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt; <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. епозода&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-sv/strings.xml b/common/res/values-sv/strings.xml
index 9911a0d..1474100 100644
--- a/common/res/values-sv/strings.xml
+++ b/common/res/values-sv/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Klar"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Hoppa över"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Säsong <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>, avsnitt <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Avsnitt <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Säsong <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: avsnitt <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> – <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Avsnitt <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> – <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Säsong<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: avsnitt <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> avsnitt. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;säsong <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, avsnitt <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;avsnitt <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-sw/strings.xml b/common/res/values-sw/strings.xml
index 7d44ced..0b6883f 100644
--- a/common/res/values-sw/strings.xml
+++ b/common/res/values-sw/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Nimemaliza"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Ruka"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Msimu wa <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Kipindi cha <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Kipindi cha <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Msimu wa <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Kipindi cha <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Kipindi cha <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>Msimu wa <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Kipindi cha <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Kipindi cha <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Msimu wa <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Kipindi cha <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Kipindi cha <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ta/strings.xml b/common/res/values-ta-rIN/strings.xml
similarity index 77%
rename from common/res/values-ta/strings.xml
rename to common/res/values-ta-rIN/strings.xml
index bc2eed6..7e3faa1 100644
--- a/common/res/values-ta/strings.xml
+++ b/common/res/values-ta-rIN/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"முடிந்தது"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"தவிர்"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"சீ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: எபி.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"எபி.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"சீ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: எபி. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"எபி. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> சீ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: எபி. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> எபி. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;சீ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: எபி. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;எபி. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-te/strings.xml b/common/res/values-te-rIN/strings.xml
similarity index 77%
rename from common/res/values-te/strings.xml
rename to common/res/values-te-rIN/strings.xml
index 80df229..066abcc 100644
--- a/common/res/values-te/strings.xml
+++ b/common/res/values-te-rIN/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"పూర్తయింది"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"దాటవేయి"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"సీ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ఎపి.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"ఎపి.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"సీ<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ఎపి. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"ఎపి. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> సీ<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ఎపి. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ఎపి. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;సీ.<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ఎపి. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ఎపి. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-th/strings.xml b/common/res/values-th/strings.xml
index 5ff9f1f..a9f94b7 100644
--- a/common/res/values-th/strings.xml
+++ b/common/res/values-th/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"เสร็จสิ้น"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"ข้าม"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"ซีซัน <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ตอนที่ <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"ตอนที่ <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"ซีซัน <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ตอนที่ <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"ตอนที่ <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ซีซัน <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ตอน <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ตอน <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ซีซัน <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ตอน <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;S"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;ตอน <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-tl/strings.xml b/common/res/values-tl/strings.xml
index e6b8bbb..24e1395 100644
--- a/common/res/values-tl/strings.xml
+++ b/common/res/values-tl/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Tapos Na"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Laktawan"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-tr/strings.xml b/common/res/values-tr/strings.xml
index c25c834..56e375f 100644
--- a/common/res/values-tr/strings.xml
+++ b/common/res/values-tr/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Bitti"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Atla"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Böl.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Böl.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>. Bölüm <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>. Bölüm <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="SEASONNUMBER">%2$s</xliff:g>.S: <xliff:g id="EPISODENUMBER">%3$s</xliff:g>. Böl."</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> <xliff:g id="EPISODENUMBER">%2$s</xliff:g>. Böl."</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Böl. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Böl. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-uk/strings.xml b/common/res/values-uk/strings.xml
index 9b67cf4..10bfb26 100644
--- a/common/res/values-uk/strings.xml
+++ b/common/res/values-uk/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Готово"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Пропустити"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Сезон <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: серія <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Серія <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Сезон <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: серія <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> \"<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>\""</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Серія <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> \"<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>\""</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"\"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\": сезон <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, серія <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"\"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\": серія <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"\"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\": &lt;i&gt;сезон <xliff:g id="SEASONNUMBER">%2$s</xliff:g>, серія <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"\"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\": &lt;i&gt;серія <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-ur/strings.xml b/common/res/values-ur-rPK/strings.xml
similarity index 77%
rename from common/res/values-ur/strings.xml
rename to common/res/values-ur-rPK/strings.xml
index b04fb3c..9edebcf 100644
--- a/common/res/values-ur/strings.xml
+++ b/common/res/values-ur-rPK/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"ہو گیا"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"نظر انداز کریں"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"سیزن<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ایپی سوڈ۔<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"ایپی سوڈ <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"سیزن <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: ایپی سوڈ <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"ایپی سوڈ <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> سیزن <xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ایپی سوڈ <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ایپی سوڈ <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"‏<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;سیزن<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: ایپی سوڈ <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"‏<xliff:g id="PROGRAMNAME">%1$s</xliff:g>  &lt;i&gt;ایپی سوڈ <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-uz/strings.xml b/common/res/values-uz-rUZ/strings.xml
similarity index 78%
rename from common/res/values-uz/strings.xml
rename to common/res/values-uz-rUZ/strings.xml
index ffa1cf9..1aef80d 100644
--- a/common/res/values-uz/strings.xml
+++ b/common/res/values-uz-rUZ/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Tayyor"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Tashlab ketish"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>-fasl: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>-qism"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>-qism"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>-fasl: <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>-qism – “<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>”"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>-qism – “<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>”"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, <xliff:g id="SEASONNUMBER">%2$s</xliff:g>-fasl <xliff:g id="EPISODENUMBER">%3$s</xliff:g>-qism"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>, <xliff:g id="EPISODENUMBER">%2$s</xliff:g>-qism"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;<xliff:g id="SEASONNUMBER">%2$s</xliff:g>-fasl <xliff:g id="EPISODENUMBER">%3$s</xliff:g>-qism&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;<xliff:g id="EPISODENUMBER">%2$s</xliff:g>-qism&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-vi/strings.xml b/common/res/values-vi/strings.xml
index 2852bb1..b7f209b 100644
--- a/common/res/values-vi/strings.xml
+++ b/common/res/values-vi/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Xong"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Bỏ qua"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"Phần<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Tập<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Tập<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"Phần <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Tập <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Tập <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> P<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Tập <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Tập <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Tập <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Tập <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-zh-rCN/strings.xml b/common/res/values-zh-rCN/strings.xml
index 25e1337..1eb99db 100644
--- a/common/res/values-zh-rCN/strings.xml
+++ b/common/res/values-zh-rCN/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"完成"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"跳过"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"第 <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> 季:第 <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> 集"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"第 <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> 集"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"第 <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> 季第 <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> 集:<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"第 <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> 集:<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》第 <xliff:g id="SEASONNUMBER">%2$s</xliff:g> 季:第 <xliff:g id="EPISODENUMBER">%3$s</xliff:g> 集"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》第 <xliff:g id="EPISODENUMBER">%2$s</xliff:g> 集"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》第 <xliff:g id="SEASONNUMBER">%2$s</xliff:g> 季:第 <xliff:g id="EPISODENUMBER">%3$s</xliff:g> 集&lt;i&gt;&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》第 <xliff:g id="EPISODENUMBER">%2$s</xliff:g> 集&lt;i&gt;&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-zh-rHK/strings.xml b/common/res/values-zh-rHK/strings.xml
index ed323c6..346db42 100644
--- a/common/res/values-zh-rHK/strings.xml
+++ b/common/res/values-zh-rHK/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"完成"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"略過"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"第 <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> 季:第 <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> 集"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"第 <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> 集"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"第 <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> 季:第 <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> 集 <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"第 <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> 集 <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》第 <xliff:g id="SEASONNUMBER">%2$s</xliff:g> 季:第 <xliff:g id="EPISODENUMBER">%3$s</xliff:g> 集"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》第 <xliff:g id="EPISODENUMBER">%2$s</xliff:g> 集"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》&lt;i&gt;第 <xliff:g id="SEASONNUMBER">%2$s</xliff:g> 季:第 <xliff:g id="EPISODENUMBER">%3$s</xliff:g> 集&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》&lt;i&gt;第 <xliff:g id="EPISODENUMBER">%2$s</xliff:g> 集&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-zh-rTW/strings.xml b/common/res/values-zh-rTW/strings.xml
index 25e1337..7cc3e3d 100644
--- a/common/res/values-zh-rTW/strings.xml
+++ b/common/res/values-zh-rTW/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"完成"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"略過"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"第 <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> 季:第 <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> 集"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"第 <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> 集"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"第 <xliff:g id="SEASON_NUMBER">%1$s</xliff:g> 季第 <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> 集:<xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"第 <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> 集:<xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》第 <xliff:g id="SEASONNUMBER">%2$s</xliff:g> 季:第 <xliff:g id="EPISODENUMBER">%3$s</xliff:g> 集"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》第 <xliff:g id="EPISODENUMBER">%2$s</xliff:g> 集"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》&lt;i&gt;第 <xliff:g id="SEASONNUMBER">%2$s</xliff:g> 季:第 <xliff:g id="EPISODENUMBER">%3$s</xliff:g> 集&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》&lt;i&gt;第 <xliff:g id="EPISODENUMBER">%2$s</xliff:g> 集&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values-zu/strings.xml b/common/res/values-zu/strings.xml
index 4574ac0..227a191 100644
--- a/common/res/values-zu/strings.xml
+++ b/common/res/values-zu/strings.xml
@@ -18,10 +18,11 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done" msgid="298287050387266501">"Kwenziwe"</string>
+    <string name="action_text_skip" msgid="9158414021827546309">"Yeqa"</string>
     <string name="display_episode_number_format" msgid="6040735693510854344">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep.<xliff:g id="EPISODE_NUMBER">%2$s</xliff:g>"</string>
     <string name="display_episode_number_format_no_season_number" msgid="8393554269654325741">"Ep.<xliff:g id="EPISODE_NUMBER">%1$s</xliff:g>"</string>
     <string name="display_episode_title_format" msgid="5041103178918130554">"S<xliff:g id="SEASON_NUMBER">%1$s</xliff:g>: Ep. <xliff:g id="EPISODE_NUMBER">%2$s</xliff:g> <xliff:g id="EPISODE_TITLE">%3$s</xliff:g>"</string>
     <string name="display_episode_title_format_no_season_number" msgid="4558449786705748989">"Ep. <xliff:g id="EPISODE_NUMBER">%1$s</xliff:g> <xliff:g id="EPISODE_TITLE">%2$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number" msgid="5708628769757639737">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>"</string>
-    <string name="program_title_with_episode_number_no_season" msgid="8299170840696856426">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>"</string>
+    <string name="program_title_with_episode_number" msgid="2159336538427523610">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;S<xliff:g id="SEASONNUMBER">%2$s</xliff:g>: Ep. <xliff:g id="EPISODENUMBER">%3$s</xliff:g>&lt;/i&gt;"</string>
+    <string name="program_title_with_episode_number_no_season" msgid="6243727201916342169">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> &lt;i&gt;Ep. <xliff:g id="EPISODENUMBER">%2$s</xliff:g>&lt;/i&gt;"</string>
 </resources>
diff --git a/common/res/values/dimens.xml b/common/res/values/dimens.xml
index 9d6e0e6..be53489 100644
--- a/common/res/values/dimens.xml
+++ b/common/res/values/dimens.xml
@@ -16,10 +16,6 @@
   -->
 
 <resources>
-    <!-- Setup screen -->
-    <dimen name="setup_fragment_enter_from">300dp</dimen>
-    <dimen name="setup_fragment_enter_to">-300dp</dimen>
-
     <!-- Guided step fragment -->
     <dimen name="setup_guidedstep_guidance_section_width_2pane">600dp</dimen>
     <dimen name="setup_guidedstep_guidance_section_width_3pane">476dp</dimen>
@@ -27,10 +23,7 @@
     <dimen name="setup_guidedactions_selector_margin_start">24dp</dimen>
     <dimen name="setup_guidedactions_selector_margin_end">24dp</dimen>
     <dimen name="setup_guidedactions_selector_margin_top">220dp</dimen>
-    <dimen name="setup_guidedactions_item_container_padding_start">40dp</dimen>
-    <dimen name="setup_guidedactions_item_container_padding_end">40dp</dimen>
     <dimen name="setup_guidedactions_vertical_padding">12dp</dimen>
-    <dimen name="setup_guidedactions_vertical_spacing">5dp</dimen>
     <item name="setup_guidedactions_width_weight" format="float" type="string">1</item>
     <dimen name="setup_guidedactions_item_delimiter_padding">10dp</dimen>
 
diff --git a/common/res/values/strings.xml b/common/res/values/strings.xml
index e5b9b62..ec02913 100644
--- a/common/res/values/strings.xml
+++ b/common/res/values/strings.xml
@@ -17,16 +17,32 @@
 
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="action_text_done">Done</string>
-    <!-- The episode display format with season and episode number used in series details view. -->
+    <string name="action_text_skip">Skip</string>
+    <!-- The episode display format with season and episode number used in series details view.
+    "S" is an abbreviation for Season and "Ep." is an abbreviation for episode.  ":" is used as a separator.
+    For example, "S1: Ep. 1"-->
     <string name="display_episode_number_format">S<xliff:g id="season_number" example="1">%1$s</xliff:g>: Ep.<xliff:g id="episode_number" example="1">%2$s</xliff:g></string>
-    <!-- The episode display format with episode number used in series details view. -->
+    <!-- The episode display format with episode number used in series details view.
+    "Ep." is an abbreviation for episode.
+    For example, "Ep. 1" -->
     <string name="display_episode_number_format_no_season_number">Ep.<xliff:g id="episode_number" example="1">%1$s</xliff:g></string>
-    <!-- The episode title format displayed on the info banner. For example, "S1: Ep. 1 Winter is coming". -->
+    <!-- The episode title format displayed on the info banner.
+    "S" is an abbreviation for Season and Ep. is an abbreviation for episode.  ":" is used as a separator.
+    For example, "S1: Ep. 1 Winter is coming". -->
     <string name="display_episode_title_format">S<xliff:g id="season_number" example="1">%1$s</xliff:g>: Ep. <xliff:g id="episode_number" example="1">%2$s</xliff:g> <xliff:g id="episode_title" example="Winter is Coming">%3$s</xliff:g></string>
-    <!-- The episode title format displayed on the info banner when the season number is not available. For example, "Ep. 1807 Headline News". -->
+    <!-- The episode title format displayed on the info banner when the season number is not available.
+    "Ep." is an abbreviation for episode.
+    For example, "Ep. 1807 Headline News". -->
     <string name="display_episode_title_format_no_season_number">Ep. <xliff:g id="episode_number" example="1807">%1$s</xliff:g> <xliff:g id="episode_title" example="Headline News">%2$s</xliff:g></string>
-    <!-- Program title with season and episode number used in DVR card views. -->
-    <string name="program_title_with_episode_number"><xliff:g id="programName" example="Big bang theory">%1$s</xliff:g> S<xliff:g id="seasonNumber" example="1">%2$s</xliff:g>: Ep. <xliff:g id="episodeNumber" example="12">%3$s</xliff:g></string>
-    <!-- Program title with episode number used in DVR card views. -->
-    <string name="program_title_with_episode_number_no_season"><xliff:g id="programName" example="Big bang theory">%1$s</xliff:g> Ep. <xliff:g id="episodeNumber" example="12">%2$s</xliff:g></string>
+    <!-- Program title with season and episode number used in DVR card views.
+    HTML tag <i> is a placeholder for styling episode number part.
+    "S" is an abbreviation for Season and "Ep." is an abbreviation for episode.  ":" is used as a separator.
+    For example "Big bang theory <i>S1: Ep. 12</i>"   -->
+    <string name="program_title_with_episode_number"><xliff:g id="programName" example="Big bang theory">%1$s</xliff:g> <![CDATA[<i>]]>S<xliff:g id="seasonNumber" example="1">%2$s</xliff:g>: Ep. <xliff:g id="episodeNumber" example="12">%3$s</xliff:g><![CDATA[</i>]]></string>
+    <!-- Program title with episode number used in DVR card views.
+    HTML tag <i> is a placeholder for styling episode number part.
+    "S" is an abbreviation for Season and "Ep." is an abbreviation for episode.  ":" is used as a separator.
+    For example "Big bang theory <i>Ep. 12</i>"
+    -->
+    <string name="program_title_with_episode_number_no_season"><xliff:g id="programName" example="Big bang theory">%1$s</xliff:g> <![CDATA[<i>]]>Ep. <xliff:g id="episodeNumber" example="12">%2$s</xliff:g><![CDATA[</i>]]></string>
 </resources>
diff --git a/common/res/values/styles.xml b/common/res/values/styles.xml
index 3c3c71c..50ef08f 100644
--- a/common/res/values/styles.xml
+++ b/common/res/values/styles.xml
@@ -57,15 +57,9 @@
         <item name="android:textSize">16sp</item>
     </style>
 
-    <style name="Widget.Setup.GuidedActionsListStyle" parent="Widget.Leanback.GuidedActionsListStyle">
-        <item name="android:elevation">0dp</item>
-    </style>
-
     <style name="Widget.Setup.GuidedActionItemContainerStyle" parent="Widget.Leanback.GuidedActionItemContainerStyle">
         <item name="android:layout_height">64dp</item>
         <item name="android:paddingBottom">@dimen/setup_guidedactions_vertical_padding</item>
-        <item name="android:paddingEnd">@dimen/setup_guidedactions_item_container_padding_end</item>
-        <item name="android:paddingStart">@dimen/setup_guidedactions_item_container_padding_start</item>
         <item name="android:paddingTop">@dimen/setup_guidedactions_vertical_padding</item>
         <item name="android:transitionGroup">true</item>
     </style>
diff --git a/common/res/values/themes.xml b/common/res/values/themes.xml
index 598ae9a..6016daf 100644
--- a/common/res/values/themes.xml
+++ b/common/res/values/themes.xml
@@ -31,7 +31,6 @@
         <item name="guidedActionItemDescriptionStyle">@style/Widget.Setup.GuidedActionItemDescriptionStyle</item>
         <item name="guidedActionsBackground">@color/common_setup_action_background</item>
         <item name="guidedActionsElevation">0dp</item>
-        <item name="guidedActionsListStyle">@style/Widget.Setup.GuidedActionsListStyle</item>
         <item name="guidedActionsSelectorDrawable">@drawable/setup_selector_background</item>
         <item name="guidedStepBackground">@android:color/transparent</item>
         <item name="setupCommonGuidanceBackground">@android:color/transparent</item>
diff --git a/common/src/com/android/tv/common/SharedPreferencesUtils.java b/common/src/com/android/tv/common/SharedPreferencesUtils.java
index fb3d9b5..140c4e6 100644
--- a/common/src/com/android/tv/common/SharedPreferencesUtils.java
+++ b/common/src/com/android/tv/common/SharedPreferencesUtils.java
@@ -35,6 +35,11 @@
     public static final String SHARED_PREF_RECURRING_RUNNER = "sharedPreferencesRecurringRunner";
     public static final String SHARED_PREF_EPG = "epg_preferences";
     public static final String SHARED_PREF_SERIES_RECORDINGS = "seriesRecordings";
+    /** No need to pre-initialize. It's used only on the worker thread. */
+    public static final String SHARED_PREF_CHANNEL_LOGO_URIS = "channelLogoUris";
+    /** Stores the UI related settings */
+    public static final String SHARED_PREF_UI_SETTINGS = "ui_settings";
+    public static final String SHARED_PREF_PREVIEW_PROGRAMS = "previewPrograms";
 
     private static boolean sInitializeCalled;
 
@@ -63,6 +68,7 @@
                     context.getSharedPreferences(SHARED_PREF_EPG, Context.MODE_PRIVATE);
                     context.getSharedPreferences(SHARED_PREF_SERIES_RECORDINGS,
                             Context.MODE_PRIVATE);
+                    context.getSharedPreferences(SHARED_PREF_UI_SETTINGS, Context.MODE_PRIVATE);
                     return null;
                 }
 
diff --git a/common/src/com/android/tv/common/TvCommonUtils.java b/common/src/com/android/tv/common/TvCommonUtils.java
index a88dd3a..c391ad2 100644
--- a/common/src/com/android/tv/common/TvCommonUtils.java
+++ b/common/src/com/android/tv/common/TvCommonUtils.java
@@ -23,6 +23,8 @@
  * Util class for common use in TV app and inputs.
  */
 public final class TvCommonUtils {
+    private static Boolean sRunningInTest;
+
     private TvCommonUtils() { }
 
     /**
@@ -58,12 +60,15 @@
      * the usual devices even the application is running in tests. We need to figure it out by
      * checking whether the class in tv-tests-common module can be loaded or not.
      */
-    public static boolean isRunningInTest() {
-        try {
-            Class.forName("com.android.tv.testing.Utils");
-            return true;
-        } catch (ClassNotFoundException e) {
-            return false;
+    public static synchronized boolean isRunningInTest() {
+        if (sRunningInTest == null) {
+            try {
+                Class.forName("com.android.tv.testing.Utils");
+                sRunningInTest = true;
+            } catch (ClassNotFoundException e) {
+                sRunningInTest = false;
+            }
         }
+        return sRunningInTest;
     }
 }
diff --git a/common/src/com/android/tv/common/TvContentRatingCache.java b/common/src/com/android/tv/common/TvContentRatingCache.java
index 5694cda..8b3c06f 100644
--- a/common/src/com/android/tv/common/TvContentRatingCache.java
+++ b/common/src/com/android/tv/common/TvContentRatingCache.java
@@ -43,6 +43,7 @@
         return INSTANCE;
     }
 
+    // @GuardedBy("TvContentRatingCache.this")
     private final Map<String, TvContentRating[]> mRatingsMultiMap = new ArrayMap<>();
 
     /**
@@ -51,7 +52,7 @@
      * Returns {@code null} if the string is empty or contains no valid ratings.
      */
     @Nullable
-    public TvContentRating[] getRatings(String commaSeparatedRatings) {
+    public synchronized TvContentRating[] getRatings(String commaSeparatedRatings) {
         if (TextUtils.isEmpty(commaSeparatedRatings)) {
             return null;
         }
@@ -136,7 +137,7 @@
     }
 
     @Override
-    public void performTrimMemory(int level) {
+    public synchronized void performTrimMemory(int level) {
         mRatingsMultiMap.clear();
     }
 
diff --git a/common/src/com/android/tv/common/feature/CommonFeatures.java b/common/src/com/android/tv/common/feature/CommonFeatures.java
index d47aa60..62c88ea 100644
--- a/common/src/com/android/tv/common/feature/CommonFeatures.java
+++ b/common/src/com/android/tv/common/feature/CommonFeatures.java
@@ -17,7 +17,6 @@
 package com.android.tv.common.feature;
 
 import static com.android.tv.common.feature.FeatureUtils.AND;
-import static com.android.tv.common.feature.FeatureUtils.OR;
 import static com.android.tv.common.feature.TestableFeature.createTestableFeature;
 
 /**
@@ -34,7 +33,7 @@
      * DVR API is introduced in N, it only works when app runs as a system app.
      */
     public static final TestableFeature DVR = createTestableFeature(
-            AND(OR(Sdk.N_PRE_2_OR_HIGHER, Sdk.AT_LEAST_N), SystemAppFeature.SYSTEM_APP_FEATURE));
+            AND(Sdk.AT_LEAST_N, SystemAppFeature.SYSTEM_APP_FEATURE));
 
     /**
      * ENABLE_RECORDING_REGARDLESS_OF_STORAGE_STATUS
diff --git a/common/src/com/android/tv/common/feature/Sdk.java b/common/src/com/android/tv/common/feature/Sdk.java
index 46a681f..9f99a64 100644
--- a/common/src/com/android/tv/common/feature/Sdk.java
+++ b/common/src/com/android/tv/common/feature/Sdk.java
@@ -18,50 +18,18 @@
 
 import android.content.Context;
 import android.os.Build;
-import android.support.v4.os.BuildCompat;
 
 /**
  *  Holder for SDK version features
  */
 public class Sdk {
-
-    public static final Feature N_PRE_2_OR_HIGHER =
-            new SdkPreviewVersionFeature(Build.VERSION_CODES.M, 2, true);
-
-    private static class SdkPreviewVersionFeature implements Feature {
-        private final int mVersionCode;
-        private final int mPreviewCode;
-        private final boolean mAllowHigherPreview;
-
-        private SdkPreviewVersionFeature(int versionCode, int previewCode,
-                boolean allowHigerPreview) {
-            mVersionCode = versionCode;
-            mPreviewCode = previewCode;
-            mAllowHigherPreview = allowHigerPreview;
-        }
-
-        @Override
-        public boolean isEnabled(Context context) {
-            try {
-                if (mAllowHigherPreview) {
-                    return Build.VERSION.SDK_INT == mVersionCode
-                            && Build.VERSION.PREVIEW_SDK_INT >= mPreviewCode;
-                } else {
-                    return Build.VERSION.SDK_INT == mVersionCode
-                            && Build.VERSION.PREVIEW_SDK_INT == mPreviewCode;
+    public static final Feature AT_LEAST_N =
+            new Feature() {
+                @Override
+                public boolean isEnabled(Context context) {
+                    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
                 }
-            } catch (NoSuchFieldError e) {
-                return false;
-            }
-        }
-    }
-
-    public static final Feature AT_LEAST_N = new Feature() {
-        @Override
-        public boolean isEnabled(Context context) {
-            return BuildCompat.isAtLeastN();
-        }
-    };
+            };
 
     private Sdk() {}
 }
diff --git a/common/src/com/android/tv/common/feature/SharedPreferencesFeature.java b/common/src/com/android/tv/common/feature/SharedPreferencesFeature.java
index a4a79b3..881f53d 100644
--- a/common/src/com/android/tv/common/feature/SharedPreferencesFeature.java
+++ b/common/src/com/android/tv/common/feature/SharedPreferencesFeature.java
@@ -19,7 +19,6 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.util.Log;
-
 import com.android.tv.common.SharedPreferencesUtils;
 
 /**
diff --git a/common/src/com/android/tv/common/feature/TestableFeature.java b/common/src/com/android/tv/common/feature/TestableFeature.java
index a02877e..d7e707a 100644
--- a/common/src/com/android/tv/common/feature/TestableFeature.java
+++ b/common/src/com/android/tv/common/feature/TestableFeature.java
@@ -36,14 +36,29 @@
     private final Feature mDelegate;
     private Boolean mTestValue = null;
 
+    /**
+     * Creates testable feature.
+     */
     public static TestableFeature createTestableFeature(Feature delegate) {
         return new TestableFeature(delegate);
     }
 
+    /**
+     * Creates testable feature with initial value.
+     */
+    public static TestableFeature createTestableFeature(Feature delegate, Boolean initialValue) {
+        return new TestableFeature(delegate, initialValue);
+    }
+
     private TestableFeature(Feature delegate) {
         mDelegate = delegate;
     }
 
+    private TestableFeature(Feature delegate, Boolean initialValue) {
+        mDelegate = delegate;
+        mTestValue = initialValue;
+    }
+
     @VisibleForTesting
     public void enableForTest() {
         if (!TvCommonUtils.isRunningInTest()) {
diff --git a/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java b/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java
index bcaefec..88159da 100644
--- a/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java
+++ b/common/src/com/android/tv/common/ui/setup/SetupGuidedStepFragment.java
@@ -72,9 +72,6 @@
         }
         // gridView Alignment
         VerticalGridView gridView = getGuidedActionsStylist().getActionsGridView();
-        // Workaround of b/28274171
-        // TODO: Remove the following line once b/28274171 is resolved.
-        gridView.setFocusable(true);
         int offset = getResources().getDimensionPixelOffset(
                 R.dimen.setup_guidedactions_selector_margin_top);
         gridView.setWindowAlignmentOffset(offset);
@@ -86,8 +83,6 @@
         ViewGroup group = (ViewGroup) view.findViewById(R.id.content_frame);
         group.setClipChildren(false);
         group.setClipToPadding(false);
-        // Workaround b/26205201
-        view.findViewById(R.id.guidedactions_list2).setFocusable(false);
         return view;
     }
 
diff --git a/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java b/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java
index 6324748..b9ad465 100644
--- a/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java
+++ b/common/src/com/android/tv/common/ui/setup/SetupMultiPaneFragment.java
@@ -34,6 +34,7 @@
     private static final boolean DEBUG = false;
 
     public static final int ACTION_DONE = Integer.MAX_VALUE;
+    public static final int ACTION_SKIP = ACTION_DONE - 1;
 
     private static final String CONTENT_FRAGMENT_TAG = "content_fragment";
 
@@ -53,7 +54,12 @@
         }
         if (needsDoneButton()) {
             setOnClickAction(view.findViewById(R.id.button_done), getActionCategory(), ACTION_DONE);
-        } else {
+        }
+        if (needsSkipButton()) {
+            view.findViewById(R.id.button_skip).setVisibility(View.VISIBLE);
+            setOnClickAction(view.findViewById(R.id.button_skip), getActionCategory(), ACTION_SKIP);
+        }
+        if (!needsDoneButton() && !needsSkipButton()) {
             View doneButtonContainer = view.findViewById(R.id.done_button_container);
             // Use content view to check layout direction while view is being created.
             if (getResources().getConfiguration().getLayoutDirection()
@@ -90,6 +96,10 @@
         return true;
     }
 
+    protected boolean needsSkipButton() {
+        return false;
+    }
+
     @Override
     protected int[] getParentIdsForDelay() {
         return new int[] {R.id.content_fragment, R.id.guidedactions_list};
@@ -99,4 +109,4 @@
     public int[] getSharedElementIds() {
         return new int[] {R.id.action_fragment_background, R.id.done_button_container};
     }
-}
+}
\ No newline at end of file
diff --git a/icu/icu4j/main/classes/core/src/com/ibm/icu/text/SCSU.java b/icu/icu4j/main/classes/core/src/com/ibm/icu/text/SCSU.java
index b12b926..39196fe 100644
--- a/icu/icu4j/main/classes/core/src/com/ibm/icu/text/SCSU.java
+++ b/icu/icu4j/main/classes/core/src/com/ibm/icu/text/SCSU.java
@@ -1,3 +1,5 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
 /*
  *******************************************************************************
  * Copyright (C) 1996-2007, International Business Machines Corporation and    *
diff --git a/icu/icu4j/main/classes/core/src/com/ibm/icu/text/UnicodeDecompressor.java b/icu/icu4j/main/classes/core/src/com/ibm/icu/text/UnicodeDecompressor.java
index e799ea1..6789469 100644
--- a/icu/icu4j/main/classes/core/src/com/ibm/icu/text/UnicodeDecompressor.java
+++ b/icu/icu4j/main/classes/core/src/com/ibm/icu/text/UnicodeDecompressor.java
@@ -1,3 +1,5 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html#License
 /*
  *******************************************************************************
  * Copyright (C) 1996-2016, International Business Machines Corporation and    *
diff --git a/jni/Android.mk b/jni/Android.mk
index 684830c..39923a1 100644
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -1,12 +1,29 @@
+#
+# Copyright (C) 2017 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.
+#
+
 LOCAL_PATH := $(call my-dir)
 
 # --------------------------------------------------------------
 include $(CLEAR_VARS)
 
-LOCAL_MODULE    := libtunertvinput_jni
+LOCAL_MODULE := libtunertvinput_jni
 LOCAL_SRC_FILES += tunertvinput_jni.cpp DvbManager.cpp
-LOCAL_SDK_VERSION := 21
+LOCAL_SDK_VERSION := 23
 LOCAL_NDK_STL_VARIANT := stlport_static
 LOCAL_LDLIBS := -llog
 
 include $(BUILD_SHARED_LIBRARY)
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/jni/DvbManager.cpp b/jni/DvbManager.cpp
index aa4ed53..941a1fa 100644
--- a/jni/DvbManager.cpp
+++ b/jni/DvbManager.cpp
@@ -42,6 +42,8 @@
           mDemuxFd(-1),
           mDvrFd(-1),
           mPatFilterFd(-1),
+          mDvbApiVersion(DVB_API_VERSION_UNDEFINED),
+          mDeliverySystemType(-1),
           mFeHasLock(false),
           mHasPendingTune(false) {
     jclass clazz = env->FindClass(
@@ -59,16 +61,26 @@
 }
 
 bool DvbManager::isFeLocked() {
-    struct pollfd pollFd;
-    pollFd.fd = mFeFd;
-    pollFd.events = POLLIN;
-    pollFd.revents = 0;
-    int poll_result = poll(&pollFd, NUM_POLLFDS, FE_POLL_TIMEOUT_MS);
-    if (poll_result > 0 && (pollFd.revents & POLLIN)) {
-        struct dvb_frontend_event kevent;
-        memset(&kevent, 0, sizeof(kevent));
-        if (ioctl(mFeFd, FE_GET_EVENT, &kevent) == 0) {
-            return (kevent.status & FE_HAS_LOCK);
+    if (mDvbApiVersion == DVB_API_VERSION5) {
+        fe_status_t status;
+        if (ioctl(mFeFd, FE_READ_STATUS, &status) < 0) {
+            return false;
+        }
+        if (status & FE_HAS_LOCK) {
+            return true;
+        }
+    } else {
+        struct pollfd pollFd;
+        pollFd.fd = mFeFd;
+        pollFd.events = POLLIN;
+        pollFd.revents = 0;
+        int poll_result = poll(&pollFd, NUM_POLLFDS, FE_POLL_TIMEOUT_MS);
+        if (poll_result > 0 && (pollFd.revents & POLLIN)) {
+            struct dvb_frontend_event kevent;
+            memset(&kevent, 0, sizeof(kevent));
+            if (ioctl(mFeFd, FE_GET_EVENT, &kevent) == 0) {
+                return (kevent.status & FE_HAS_LOCK);
+            }
         }
     }
     return false;
@@ -78,38 +90,111 @@
         const int frequency, const char *modulationStr, int timeout_ms) {
     resetExceptFe();
 
-    struct dvb_frontend_parameters feParams;
-    memset(&feParams, 0, sizeof(struct dvb_frontend_parameters));
-    feParams.frequency = frequency;
-    if (strcmp(modulationStr, "8VSB") == 0) {
-        feParams.u.vsb.modulation = VSB_8;
-    } else if (strcmp(modulationStr, "QAM256") == 0) {
-        feParams.u.vsb.modulation = QAM_256;
-    } else {
-        ALOGE("Unrecognized modulation mode : %s", modulationStr);
-        return -1;
-    }
-
-    if (mHasPendingTune) {
-        return -1;
-    }
     if (openDvbFe(env, thiz) != 0) {
         return -1;
     }
-
-    feParams.inversion = INVERSION_AUTO;
-    /* Check frontend capability */
-    struct dvb_frontend_info feInfo;
-    if (ioctl(mFeFd, FE_GET_INFO, &feInfo) != -1) {
-        if (!(feInfo.caps & FE_CAN_INVERSION_AUTO)) {
-            // FE can't do INVERSION_AUTO, trying INVERSION_OFF instead
-            feParams.inversion = INVERSION_OFF;
+    if (mDvbApiVersion == DVB_API_VERSION_UNDEFINED) {
+        struct dtv_property testProps[1] = {
+            { .cmd = DTV_DELIVERY_SYSTEM }
+        };
+        struct dtv_properties feProp = {
+            .num = 1, .props = testProps
+        };
+        // On fugu, DVB_API_VERSION is 5 but it doesn't support FE_SET_PROPERTY. Checking the device
+        // support FE_GET_PROPERTY or not to determine the DVB API version is greater than 5 or not.
+        if (ioctl(mFeFd, FE_GET_PROPERTY, &feProp) == -1) {
+            ALOGD("FE_GET_PROPERTY failed, %s", strerror(errno));
+            mDvbApiVersion = DVB_API_VERSION3;
+        } else {
+            mDvbApiVersion = DVB_API_VERSION5;
         }
     }
 
-    if (ioctl(mFeFd, FE_SET_FRONTEND, &feParams) != 0) {
-        ALOGD("Can't set Frontend : %s", strerror(errno));
-        return -1;
+    if (mDvbApiVersion == DVB_API_VERSION5) {
+        struct dtv_property deliverySystemProperty = {
+            .cmd = DTV_DELIVERY_SYSTEM, .u.data = SYS_ATSC
+        };
+        struct dtv_property frequencyProperty = {
+            .cmd = DTV_FREQUENCY, .u.data = frequency
+        };
+        struct dtv_property modulationProperty = { .cmd = DTV_MODULATION };
+        if (strncmp(modulationStr, "QAM", 3) == 0) {
+            modulationProperty.u.data = QAM_AUTO;
+        } else if (strcmp(modulationStr, "8VSB") == 0) {
+            modulationProperty.u.data = VSB_8;
+        } else {
+            ALOGE("Unrecognized modulation mode : %s", modulationStr);
+            return -1;
+        }
+        struct dtv_property tuneProperty = { .cmd = DTV_TUNE };
+
+        struct dtv_property props[] = {
+                deliverySystemProperty, frequencyProperty, modulationProperty, tuneProperty
+        };
+        struct dtv_properties dtvProperty = {
+            .num = 4, .props = props
+        };
+
+        if (mHasPendingTune) {
+            return -1;
+        }
+        if (ioctl(mFeFd, FE_SET_PROPERTY, &dtvProperty) != 0) {
+            ALOGD("Can't set Frontend : %s", strerror(errno));
+            return -1;
+        }
+    } else {
+        struct dvb_frontend_parameters feParams;
+        memset(&feParams, 0, sizeof(struct dvb_frontend_parameters));
+        feParams.frequency = frequency;
+        feParams.inversion = INVERSION_AUTO;
+        /* Check frontend capability */
+        struct dvb_frontend_info feInfo;
+        if (ioctl(mFeFd, FE_GET_INFO, &feInfo) != -1) {
+            if (!(feInfo.caps & FE_CAN_INVERSION_AUTO)) {
+                // FE can't do INVERSION_AUTO, trying INVERSION_OFF instead
+                feParams.inversion = INVERSION_OFF;
+            }
+        }
+        switch (feInfo.type) {
+            case FE_ATSC:
+                if (strcmp(modulationStr, "8VSB") == 0) {
+                    feParams.u.vsb.modulation = VSB_8;
+                } else if (strncmp(modulationStr, "QAM", 3) == 0) {
+                    feParams.u.vsb.modulation = QAM_AUTO;
+                } else {
+                    ALOGE("Unrecognized modulation mode : %s", modulationStr);
+                    return -1;
+                }
+                break;
+            case FE_OFDM:
+                if (strcmp(modulationStr, "8VSB") == 0) {
+                    feParams.u.ofdm.constellation = VSB_8;
+                } else if (strcmp(modulationStr, "QAM16") == 0) {
+                    feParams.u.ofdm.constellation = QAM_16;
+                } else if (strcmp(modulationStr, "QAM64") == 0) {
+                    feParams.u.ofdm.constellation = QAM_64;
+                } else if (strcmp(modulationStr, "QAM256") == 0) {
+                    feParams.u.ofdm.constellation = QAM_256;
+                } else if (strcmp(modulationStr, "QPSK") == 0) {
+                    feParams.u.ofdm.constellation = QPSK;
+                } else {
+                    ALOGE("Unrecognized modulation mode : %s", modulationStr);
+                    return -1;
+                }
+                break;
+            default:
+                ALOGE("Unsupported delivery system.");
+                return -1;
+        }
+
+        if (mHasPendingTune) {
+            return -1;
+        }
+
+        if (ioctl(mFeFd, FE_SET_FRONTEND, &feParams) != 0) {
+            ALOGD("Can't set Frontend : %s", strerror(errno));
+            return -1;
+        }
     }
 
     int lockSuccessCount = 0;
@@ -238,6 +323,10 @@
         return -1;
     }
 
+    if (mDvbApiVersion == DVB_API_VERSION5) {
+        ioctl(demuxFd, DMX_START, 0);
+    }
+
     if (pid != PAT_PID) {
         mPidFilters.insert(std::pair<int, int>(pid, demuxFd));
     } else {
@@ -337,3 +426,75 @@
 void DvbManager::setHasPendingTune(bool hasPendingTune) {
     mHasPendingTune = hasPendingTune;
 }
+
+int DvbManager::getDeliverySystemType(JNIEnv *env, jobject thiz) {
+    if (mDeliverySystemType != -1) {
+        return mDeliverySystemType;
+    }
+    if (mFeFd == -1) {
+        if ((mFeFd = openDvbFeFromSystemApi(env, thiz)) < 0) {
+            ALOGD("Can't open FE file : %s", strerror(errno));
+            return DELIVERY_SYSTEM_UNDEFINED;
+        }
+    }
+    struct dtv_property testProps[1] = {
+        { .cmd = DTV_DELIVERY_SYSTEM }
+    };
+    struct dtv_properties feProp = {
+        .num = 1, .props = testProps
+    };
+    mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED;
+    if (ioctl(mFeFd, FE_GET_PROPERTY, &feProp) == -1) {
+        mDvbApiVersion = DVB_API_VERSION3;
+        if (openDvbFe(env, thiz) == 0) {
+            struct dvb_frontend_info info;
+            if (ioctl(mFeFd, FE_GET_INFO, &info) == 0) {
+                switch (info.type) {
+                    case FE_QPSK:
+                        mDeliverySystemType = DELIVERY_SYSTEM_DVBS;
+                        break;
+                    case FE_QAM:
+                        mDeliverySystemType = DELIVERY_SYSTEM_DVBC;
+                        break;
+                    case FE_OFDM:
+                        mDeliverySystemType = DELIVERY_SYSTEM_DVBT;
+                        break;
+                    case FE_ATSC:
+                        mDeliverySystemType = DELIVERY_SYSTEM_ATSC;
+                        break;
+                    default:
+                        mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED;
+                        break;
+                }
+            }
+        }
+    } else {
+        mDvbApiVersion = DVB_API_VERSION5;
+        switch (feProp.props[0].u.data) {
+            case SYS_DVBT:
+                mDeliverySystemType = DELIVERY_SYSTEM_DVBT;
+                break;
+            case SYS_DVBT2:
+                mDeliverySystemType = DELIVERY_SYSTEM_DVBT2;
+                break;
+            case SYS_DVBS:
+                mDeliverySystemType = DELIVERY_SYSTEM_DVBS;
+                break;
+            case SYS_DVBS2:
+                mDeliverySystemType = DELIVERY_SYSTEM_DVBS2;
+                break;
+            case SYS_DVBC_ANNEX_A:
+            case SYS_DVBC_ANNEX_B:
+            case SYS_DVBC_ANNEX_C:
+                mDeliverySystemType = DELIVERY_SYSTEM_DVBC;
+                break;
+            case SYS_ATSC:
+                mDeliverySystemType = DELIVERY_SYSTEM_ATSC;
+                break;
+            default:
+                mDeliverySystemType = DELIVERY_SYSTEM_UNDEFINED;
+                break;
+        }
+    }
+    return mDeliverySystemType;
+}
\ No newline at end of file
diff --git a/jni/DvbManager.h b/jni/DvbManager.h
index 7475bd4..2252332 100644
--- a/jni/DvbManager.h
+++ b/jni/DvbManager.h
@@ -31,6 +31,9 @@
     static const int DVB_TUNE_STOP_DELAY_MS = 100 * 1000;
     static const int FE_POLL_TIMEOUT_MS = 100;
     static const int PAT_PID = 0;
+    static const int DVB_API_VERSION_UNDEFINED = -1;
+    static const int DVB_API_VERSION3 = 3;
+    static const int DVB_API_VERSION5 = 5;
 
     static const int FILTER_TYPE_OTHER =
             com_android_tv_tuner_TunerHal_FILTER_TYPE_OTHER;
@@ -41,10 +44,28 @@
     static const int FILTER_TYPE_PCR =
             com_android_tv_tuner_TunerHal_FILTER_TYPE_PCR;
 
+    static const int DELIVERY_SYSTEM_UNDEFINED =
+            com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_UNDEFINED;
+    static const int DELIVERY_SYSTEM_ATSC =
+            com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_ATSC;
+    static const int DELIVERY_SYSTEM_DVBC =
+            com_android_tv_tuner_TunerHal_DDELIVERY_SYSTEM_DVBC;
+    static const int DELIVERY_SYSTEM_DVBS =
+            com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBS;
+    static const int DELIVERY_SYSTEM_DVBS2 =
+            com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBS2;
+    static const int DELIVERY_SYSTEM_DVBT =
+            com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBT;
+    static const int DELIVERY_SYSTEM_DVBT2 =
+            com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBT2;
+
+
     int mFeFd;
     int mDemuxFd;
     int mDvrFd;
     int mPatFilterFd;
+    int mDvbApiVersion;
+    int mDeliverySystemType;
     bool mFeHasLock;
     // Flag for pending tune request. Used for canceling the current tune operation.
     bool volatile mHasPendingTune;
@@ -65,6 +86,7 @@
     int startTsPidFilter(JNIEnv *env, jobject thiz, int pid, int filterType);
     void closeAllDvbPidFilter();
     void setHasPendingTune(bool hasPendingTune);
+    int getDeliverySystemType(JNIEnv *env, jobject thiz);
 
 private:
     int openDvbFe(JNIEnv *env, jobject thiz);
diff --git a/jni/minijail/Android.mk b/jni/minijail/Android.mk
new file mode 100644
index 0000000..940237d
--- /dev/null
+++ b/jni/minijail/Android.mk
@@ -0,0 +1,28 @@
+#
+# Copyright (C) 2017 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# --------------------------------------------------------------
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libminijail_jni
+LOCAL_SRC_FILES := minijail.cpp
+LOCAL_CXX_STL := none
+LOCAL_STATIC_LIBRARIES := libc++_static libminijail
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/jni/minijail/minijail.cpp b/jni/minijail/minijail.cpp
new file mode 100644
index 0000000..9eebc49
--- /dev/null
+++ b/jni/minijail/minijail.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "minijail.h"
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+
+#include <libminijail.h>
+#include <scoped_minijail.h>
+#include <android/log.h>
+
+#ifndef LOG_TAG
+#define LOG_TAG "minijail"
+#endif
+
+#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR  , LOG_TAG, __VA_ARGS__)
+
+
+/*
+ * Class:     com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService
+ * Method:    nativeSetupMinijail
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL
+Java_com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_nativeSetupMinijail
+(JNIEnv *, jobject, jint policyFd) {
+    ScopedMinijail jail{minijail_new()};
+    if (!jail) {
+        ALOGE("Failed to create minijail");
+    }
+
+    minijail_no_new_privs(jail.get());
+    minijail_log_seccomp_filter_failures(jail.get());
+    minijail_use_seccomp_filter(jail.get());
+    minijail_set_seccomp_filter_tsync(jail.get());
+    // Transfer ownership of |policy_fd|.
+    minijail_parse_seccomp_filters_from_fd(jail.get(), policyFd);
+    minijail_enter(jail.get());
+    close(policyFd);
+}
+
+/*
+ * Class:     com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService
+ * Method:    nativeTestMinijail
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL
+Java_com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_nativeTestMinijail
+(JNIEnv *, jobject) {
+    kill(getpid(), SIGUSR1);
+}
\ No newline at end of file
diff --git a/jni/minijail/minijail.h b/jni/minijail/minijail.h
new file mode 100644
index 0000000..cdf272c
--- /dev/null
+++ b/jni/minijail/minijail.h
@@ -0,0 +1,44 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService */
+
+#ifndef _Included_com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService
+#define _Included_com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_DEBUG
+#define com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_DEBUG 0L
+#undef com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_MINIJAIL_SETUP_WAIT_TIMEOUT_MS
+#define com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_MINIJAIL_SETUP_WAIT_TIMEOUT_MS 5000LL
+/*
+ * Class:     com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService
+ * Method:    nativeSetupMinijail
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_nativeSetupMinijail
+  (JNIEnv *, jobject, jint);
+
+/*
+ * Class:     com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService
+ * Method:    nativeTestMinijail
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_nativeTestMinijail
+  (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_FfmpegDecoder */
+
+#ifndef _Included_com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_FfmpegDecoder
+#define _Included_com_android_tv_tuner_exoplayer_ffmpeg_FfmpegDecoderService_FfmpegDecoder
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
diff --git a/jni/tunertvinput_jni.cpp b/jni/tunertvinput_jni.cpp
index bcbc4c2..5b1a161 100644
--- a/jni/tunertvinput_jni.cpp
+++ b/jni/tunertvinput_jni.cpp
@@ -155,3 +155,21 @@
         it->second->setHasPendingTune(hasPendingTune);
     }
 }
+
+/*
+ * Class:     com_android_tv_tuner_TunerHal
+ * Method:    nativeGetDeliverySystemType
+ * Signature: (J)I
+ */
+JNIEXPORT int JNICALL
+Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemType
+(JNIEnv *env, jobject thiz, jlong deviceId) {
+    std::map<jlong, DvbManager *>::iterator it = sDvbManagers.find(deviceId);
+    if (it != sDvbManagers.end()) {
+        return it->second->getDeliverySystemType(env, thiz);
+    } else {
+        DvbManager *dvbManager = new DvbManager(env, thiz);
+        sDvbManagers.insert(std::pair<jlong, DvbManager *>(deviceId, dvbManager));
+        return dvbManager->getDeliverySystemType(env, thiz);
+    }
+}
\ No newline at end of file
diff --git a/jni/tunertvinput_jni.h b/jni/tunertvinput_jni.h
index 4ade29e..fcd64d5 100644
--- a/jni/tunertvinput_jni.h
+++ b/jni/tunertvinput_jni.h
@@ -25,6 +25,20 @@
 #define com_android_tv_tuner_TunerHal_DEFAULT_VSB_TUNE_TIMEOUT_MS 2000L
 #undef com_android_tv_tuner_TunerHal_DEFAULT_QAM_TUNE_TIMEOUT_MS
 #define com_android_tv_tuner_TunerHal_DEFAULT_QAM_TUNE_TIMEOUT_MS 4000L
+#undef com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_UNDEFINED
+#define com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_UNDEFINED 0L
+#undef com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_ATSC
+#define com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_ATSC 1L
+#undef com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBC
+#define com_android_tv_tuner_TunerHal_DDELIVERY_SYSTEM_DVBC 2L
+#undef com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBS
+#define com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBS 3L
+#undef com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBS2
+#define com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBS2 4L
+#undef com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBT
+#define com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBT 5L
+#undef com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBT2
+#define com_android_tv_tuner_TunerHal_DELIVERY_SYSTEM_DVBT2 6L
 /*
  * Class:     com_android_tv_tuner_TunerHal
  * Method:    nativeFinalize
@@ -81,6 +95,14 @@
 JNIEXPORT void JNICALL Java_com_android_tv_tuner_TunerHal_nativeSetHasPendingTune
   (JNIEnv *, jobject, jlong, jboolean);
 
+/*
+ * Class:     com_android_tv_tuner_TunerHal
+ * Method:    nativeGetDeliverySystemType
+ * Signature: (J)I
+ */
+JNIEXPORT int JNICALL Java_com_android_tv_tuner_TunerHal_nativeGetDeliverySystemType
+  (JNIEnv *, jobject, jlong);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/exoplayer_v2.jar b/libs/exoplayer_v2.jar
new file mode 100644
index 0000000..6cfcde9
--- /dev/null
+++ b/libs/exoplayer_v2.jar
Binary files differ
diff --git a/libs/exoplayer_v2_ext_ffmpeg.jar b/libs/exoplayer_v2_ext_ffmpeg.jar
new file mode 100644
index 0000000..6511726
--- /dev/null
+++ b/libs/exoplayer_v2_ext_ffmpeg.jar
Binary files differ
diff --git a/proguard.flags b/proguard.flags
index 6ffed3e..0edd14f 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -38,6 +38,9 @@
     long getSize();
     void close();
 }
+-keepclasseswithmembers class com.google.android.exoplayer2.ext.ffmpeg {
+   native <methods>;
+}
 
 # Keep method which is used for reflection.
 -keep @com.android.tv.common.annotation.UsedByReflection class *  {*;}
@@ -53,3 +56,4 @@
 
 # Grpc used by epg via reflection
 -keep class io.grpc.internal.DnsNameResolverProvider
+
diff --git a/proto/channel.proto b/proto/channel.proto
index 982a1aa..b4e67e0 100644
--- a/proto/channel.proto
+++ b/proto/channel.proto
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+syntax = 'proto2';
+
 package com.android.tv.tuner.data;
 
 option java_package = "com.android.tv.tuner.data";
@@ -45,12 +47,15 @@
   repeated AtscCaptionTrack caption_tracks = 20;
   optional bool has_caption_track = 21;
   optional AtscServiceType service_type = 22 [default = SERVICE_TYPE_ATSC_DIGITAL_TELEVISION];
+  optional bool recording_prohibited = 23;
+  optional string video_format = 24;
 }
 
 // Enum describing the types of tuner.
 enum TunerType {
   TYPE_TUNER = 0;
   TYPE_FILE = 1;
+  TYPE_NETWORK = 2;
 }
 
 // Enum describing the types of video stream.
diff --git a/proto/track.proto b/proto/track.proto
index 62b8f27..fe60fed 100644
--- a/proto/track.proto
+++ b/proto/track.proto
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+syntax = "proto2";
+
 package com.android.tv.tuner.data;
 
 option java_package = "com.android.tv.tuner.data";
diff --git a/res/drawable-xhdpi/cloud01.png b/res/drawable-xhdpi/cloud01.png
index 2bb6a2a..75f81ce 100644
--- a/res/drawable-xhdpi/cloud01.png
+++ b/res/drawable-xhdpi/cloud01.png
Binary files differ
diff --git a/res/drawable-xhdpi/cloud02.png b/res/drawable-xhdpi/cloud02.png
index 35c9746..25dc3bc 100644
--- a/res/drawable-xhdpi/cloud02.png
+++ b/res/drawable-xhdpi/cloud02.png
Binary files differ
diff --git a/res/drawable-xhdpi/dvr_default_poster.png b/res/drawable-xhdpi/dvr_default_poster.png
index 683a693..fd752af 100644
--- a/res/drawable-xhdpi/dvr_default_poster.png
+++ b/res/drawable-xhdpi/dvr_default_poster.png
Binary files differ
diff --git a/res/drawable-xhdpi/dvr_default_program_art.png b/res/drawable-xhdpi/dvr_default_program_art.png
deleted file mode 100644
index 6a8d68e..0000000
--- a/res/drawable-xhdpi/dvr_default_program_art.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_channel_guide.png b/res/drawable-xhdpi/ic_channel_guide.png
index 526b2f6..8051202 100644
--- a/res/drawable-xhdpi/ic_channel_guide.png
+++ b/res/drawable-xhdpi/ic_channel_guide.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_delete_32dp.png b/res/drawable-xhdpi/ic_delete_32dp.png
index b3e9754..7393a65 100644
--- a/res/drawable-xhdpi/ic_delete_32dp.png
+++ b/res/drawable-xhdpi/ic_delete_32dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_developer_mode_tv_white_48dp.png b/res/drawable-xhdpi/ic_developer_mode_tv_white_48dp.png
old mode 100755
new mode 100644
index ab2949b..594af85
--- a/res/drawable-xhdpi/ic_developer_mode_tv_white_48dp.png
+++ b/res/drawable-xhdpi/ic_developer_mode_tv_white_48dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dvr.png b/res/drawable-xhdpi/ic_dvr.png
index 347db04..512ae00 100644
--- a/res/drawable-xhdpi/ic_dvr.png
+++ b/res/drawable-xhdpi/ic_dvr.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dvr_cancel.png b/res/drawable-xhdpi/ic_dvr_cancel.png
index bc761c7..6d6165e 100644
--- a/res/drawable-xhdpi/ic_dvr_cancel.png
+++ b/res/drawable-xhdpi/ic_dvr_cancel.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dvr_cancel_32dp.png b/res/drawable-xhdpi/ic_dvr_cancel_32dp.png
index 339247e..8c83468 100644
--- a/res/drawable-xhdpi/ic_dvr_cancel_32dp.png
+++ b/res/drawable-xhdpi/ic_dvr_cancel_32dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dvr_cancel_large.png b/res/drawable-xhdpi/ic_dvr_cancel_large.png
index f3686d0..4a1aed3 100644
--- a/res/drawable-xhdpi/ic_dvr_cancel_large.png
+++ b/res/drawable-xhdpi/ic_dvr_cancel_large.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_dvr_delete.png b/res/drawable-xhdpi/ic_dvr_delete.png
index bcdca67..5054af9 100644
--- a/res/drawable-xhdpi/ic_dvr_delete.png
+++ b/res/drawable-xhdpi/ic_dvr_delete.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_error_recording.png b/res/drawable-xhdpi/ic_error_recording.png
deleted file mode 100644
index 5878c3b..0000000
--- a/res/drawable-xhdpi/ic_error_recording.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_error_white_48dp.png b/res/drawable-xhdpi/ic_error_white_48dp.png
index e8e8ab5..8c2cf1e 100644
--- a/res/drawable-xhdpi/ic_error_white_48dp.png
+++ b/res/drawable-xhdpi/ic_error_white_48dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_fresh.png b/res/drawable-xhdpi/ic_fresh.png
deleted file mode 100644
index c1bc958..0000000
--- a/res/drawable-xhdpi/ic_fresh.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_guide_lock.png b/res/drawable-xhdpi/ic_guide_lock.png
index e36bd12..b0efff1 100644
--- a/res/drawable-xhdpi/ic_guide_lock.png
+++ b/res/drawable-xhdpi/ic_guide_lock.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_launcher_s.png b/res/drawable-xhdpi/ic_launcher_s.png
index 8fe7fd5..552992d 100644
--- a/res/drawable-xhdpi/ic_launcher_s.png
+++ b/res/drawable-xhdpi/ic_launcher_s.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_message_lock_no_permission.png b/res/drawable-xhdpi/ic_message_lock_no_permission.png
index bb99697..8fbd256 100644
--- a/res/drawable-xhdpi/ic_message_lock_no_permission.png
+++ b/res/drawable-xhdpi/ic_message_lock_no_permission.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_message_lock_preview.png b/res/drawable-xhdpi/ic_message_lock_preview.png
index 69a5eed..8a99c36 100644
--- a/res/drawable-xhdpi/ic_message_lock_preview.png
+++ b/res/drawable-xhdpi/ic_message_lock_preview.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_input.png b/res/drawable-xhdpi/ic_pip_option_input.png
deleted file mode 100644
index 47c5006..0000000
--- a/res/drawable-xhdpi/ic_pip_option_input.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_layout1.png b/res/drawable-xhdpi/ic_pip_option_layout1.png
deleted file mode 100644
index 14b2602..0000000
--- a/res/drawable-xhdpi/ic_pip_option_layout1.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_layout2.png b/res/drawable-xhdpi/ic_pip_option_layout2.png
deleted file mode 100644
index e5d7727..0000000
--- a/res/drawable-xhdpi/ic_pip_option_layout2.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_layout3.png b/res/drawable-xhdpi/ic_pip_option_layout3.png
deleted file mode 100644
index dfe110d..0000000
--- a/res/drawable-xhdpi/ic_pip_option_layout3.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_layout4.png b/res/drawable-xhdpi/ic_pip_option_layout4.png
deleted file mode 100644
index 8ab5fa4..0000000
--- a/res/drawable-xhdpi/ic_pip_option_layout4.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_layout5.png b/res/drawable-xhdpi/ic_pip_option_layout5.png
deleted file mode 100644
index d6b5364..0000000
--- a/res/drawable-xhdpi/ic_pip_option_layout5.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_size.png b/res/drawable-xhdpi/ic_pip_option_size.png
deleted file mode 100644
index 96fb0b0..0000000
--- a/res/drawable-xhdpi/ic_pip_option_size.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_swap.png b/res/drawable-xhdpi/ic_pip_option_swap.png
deleted file mode 100644
index fa2088e..0000000
--- a/res/drawable-xhdpi/ic_pip_option_swap.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_pip_option_swap_audio.png b/res/drawable-xhdpi/ic_pip_option_swap_audio.png
deleted file mode 100644
index a5f5431..0000000
--- a/res/drawable-xhdpi/ic_pip_option_swap_audio.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_record_start.png b/res/drawable-xhdpi/ic_record_start.png
index 53e3f03..bae336c 100644
--- a/res/drawable-xhdpi/ic_record_start.png
+++ b/res/drawable-xhdpi/ic_record_start.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_recorded_program.png b/res/drawable-xhdpi/ic_recorded_program.png
deleted file mode 100644
index fe22714..0000000
--- a/res/drawable-xhdpi/ic_recorded_program.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_related_actor.png b/res/drawable-xhdpi/ic_related_actor.png
deleted file mode 100644
index 9b726b9..0000000
--- a/res/drawable-xhdpi/ic_related_actor.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_related_search.png b/res/drawable-xhdpi/ic_related_search.png
deleted file mode 100644
index aa5cd0d..0000000
--- a/res/drawable-xhdpi/ic_related_search.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_schedule_32dp.png b/res/drawable-xhdpi/ic_schedule_32dp.png
index b3e4bb5..a665c6f 100644
--- a/res/drawable-xhdpi/ic_schedule_32dp.png
+++ b/res/drawable-xhdpi/ic_schedule_32dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_scheduled_recording.png b/res/drawable-xhdpi/ic_scheduled_recording.png
index 520823a..fbe2cd8 100644
--- a/res/drawable-xhdpi/ic_scheduled_recording.png
+++ b/res/drawable-xhdpi/ic_scheduled_recording.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_scheduled_white.png b/res/drawable-xhdpi/ic_scheduled_white.png
index 49778de..40814e4 100644
--- a/res/drawable-xhdpi/ic_scheduled_white.png
+++ b/res/drawable-xhdpi/ic_scheduled_white.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_setup_antenna.png b/res/drawable-xhdpi/ic_setup_antenna.png
deleted file mode 100644
index bb6d416..0000000
--- a/res/drawable-xhdpi/ic_setup_antenna.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_setup_channels.png b/res/drawable-xhdpi/ic_setup_channels.png
index 03ff850..fcfd596 100644
--- a/res/drawable-xhdpi/ic_setup_channels.png
+++ b/res/drawable-xhdpi/ic_setup_channels.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tvoption_multi_track.png b/res/drawable-xhdpi/ic_tvoption_multi_track.png
index d1aff33..e0a42e7 100644
--- a/res/drawable-xhdpi/ic_tvoption_multi_track.png
+++ b/res/drawable-xhdpi/ic_tvoption_multi_track.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tvoption_pip.png b/res/drawable-xhdpi/ic_tvoption_pip.png
index 0f78d83..e5d7727 100644
--- a/res/drawable-xhdpi/ic_tvoption_pip.png
+++ b/res/drawable-xhdpi/ic_tvoption_pip.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tvoption_pip_off.png b/res/drawable-xhdpi/ic_tvoption_pip_off.png
deleted file mode 100644
index 6001677..0000000
--- a/res/drawable-xhdpi/ic_tvoption_pip_off.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/ic_tvsidepanel_partial_locked.png b/res/drawable-xhdpi/ic_tvsidepanel_partial_locked.png
index 0997a2a..18a12f4 100644
--- a/res/drawable-xhdpi/ic_tvsidepanel_partial_locked.png
+++ b/res/drawable-xhdpi/ic_tvsidepanel_partial_locked.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_warning_gray600_36dp.png b/res/drawable-xhdpi/ic_warning_gray600_36dp.png
index 7c08b8f..8a84d3b 100644
--- a/res/drawable-xhdpi/ic_warning_gray600_36dp.png
+++ b/res/drawable-xhdpi/ic_warning_gray600_36dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_warning_white_12dp.png b/res/drawable-xhdpi/ic_warning_white_12dp.png
index 7123470..91856a9 100644
--- a/res/drawable-xhdpi/ic_warning_white_12dp.png
+++ b/res/drawable-xhdpi/ic_warning_white_12dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_warning_white_18dp.png b/res/drawable-xhdpi/ic_warning_white_18dp.png
index 1e69e39..13d573e 100644
--- a/res/drawable-xhdpi/ic_warning_white_18dp.png
+++ b/res/drawable-xhdpi/ic_warning_white_18dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_warning_white_32dp.png b/res/drawable-xhdpi/ic_warning_white_32dp.png
index f5267b5..86f9877 100644
--- a/res/drawable-xhdpi/ic_warning_white_32dp.png
+++ b/res/drawable-xhdpi/ic_warning_white_32dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_warning_white_96dp.png b/res/drawable-xhdpi/ic_warning_white_96dp.png
index de684e4..50d1f29 100644
--- a/res/drawable-xhdpi/ic_warning_white_96dp.png
+++ b/res/drawable-xhdpi/ic_warning_white_96dp.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_welcome_ripple_000.png b/res/drawable-xhdpi/ic_welcome_ripple_000.png
index c4aac06..2ffb55d 100644
--- a/res/drawable-xhdpi/ic_welcome_ripple_000.png
+++ b/res/drawable-xhdpi/ic_welcome_ripple_000.png
Binary files differ
diff --git a/res/drawable-xhdpi/tv_3a_00.png b/res/drawable-xhdpi/tv_3a_00.png
deleted file mode 100644
index ad8f256..0000000
--- a/res/drawable-xhdpi/tv_3a_00.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tv_error.png b/res/drawable-xhdpi/tv_error.png
deleted file mode 100644
index 718f203..0000000
--- a/res/drawable-xhdpi/tv_error.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/tv_usb_antenna.png b/res/drawable-xhdpi/tv_usb_antenna.png
deleted file mode 100644
index ff6c5cc..0000000
--- a/res/drawable-xhdpi/tv_usb_antenna.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable/play_controls_time_indicator.xml b/res/drawable/play_controls_time_indicator.xml
index 16acb10..85fee1f 100644
--- a/res/drawable/play_controls_time_indicator.xml
+++ b/res/drawable/play_controls_time_indicator.xml
@@ -17,7 +17,5 @@
 
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="oval" >
-    <size android:width="@dimen/play_controls_time_indicator_width"
-        android:height="@dimen/play_controls_time_indicator_height" />
     <solid android:color="@color/play_controls_progress_time_indicator_color" />
 </shape>
diff --git a/res/drawable/playback_progress_bar.xml b/res/drawable/playback_progress_bar.xml
new file mode 100644
index 0000000..2a70ec8
--- /dev/null
+++ b/res/drawable/playback_progress_bar.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 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.
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background">
+        <shape>
+            <solid android:color="@color/play_controls_progress_bar_background" />
+        </shape>
+    </item>
+    <item android:id="@android:id/secondaryProgress">
+        <shape>
+            <solid android:color="@color/play_controls_progress_bar_buffered" />
+        </shape>
+    </item>
+    <item android:id="@android:id/progress">
+        <shape>
+            <solid android:color="@color/play_controls_progress_bar_watched" />
+        </shape>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/drawable/priority_settings_action_item_selected.xml b/res/drawable/priority_settings_action_item_selected.xml
index a1ab18a..3e01731 100644
--- a/res/drawable/priority_settings_action_item_selected.xml
+++ b/res/drawable/priority_settings_action_item_selected.xml
@@ -15,12 +15,8 @@
   ~ limitations under the License.
   -->
 
-<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:left="24dp" android:right="24dp">
-        <shape>
-            <solid android:color="#EEEEEE"/>
-            <corners android:radius="2dp" />
-        </shape>
-    </item>
-</layer-list>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <solid android:color="#EEEEEE"/>
+    <corners android:radius="2dp" />
+</shape>
 
diff --git a/res/drawable/setup_item_background.xml b/res/drawable/setup_item_background.xml
deleted file mode 100644
index fb3899a..0000000
--- a/res/drawable/setup_item_background.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:enterFadeDuration="@android:integer/config_shortAnimTime"
-    android:exitFadeDuration="@android:integer/config_shortAnimTime"
-    android:color="?android:attr/colorControlHighlight">
-    <item android:id="@android:id/mask">
-        <shape android:shape="rectangle" >
-            <solid android:color="@android:color/white" />
-            <corners android:radius="2dp" />
-        </shape>
-    </item>
-</ripple>
diff --git a/res/layout/activity_dvr_playback.xml b/res/layout/activity_dvr_playback.xml
index 204001c..02641d8 100644
--- a/res/layout/activity_dvr_playback.xml
+++ b/res/layout/activity_dvr_playback.xml
@@ -34,7 +34,11 @@
     </FrameLayout>
 
     <fragment android:id="@+id/dvr_playback_controls_fragment"
-        android:name="com.android.tv.dvr.ui.DvrPlaybackOverlayFragment"
+        android:name="com.android.tv.dvr.ui.playback.DvrPlaybackOverlayFragment"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+    <FrameLayout android:id="@+id/dvr_playback_side_fragment"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
 
diff --git a/res/layout/activity_dvr_schedules.xml b/res/layout/activity_dvr_schedules.xml
index 61e1f2a..43b2286 100644
--- a/res/layout/activity_dvr_schedules.xml
+++ b/res/layout/activity_dvr_schedules.xml
@@ -16,6 +16,7 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/dvr_schedules"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
diff --git a/res/layout/activity_tv.xml b/res/layout/activity_tv.xml
index f766ae0..b6a0a3a 100644
--- a/res/layout/activity_tv.xml
+++ b/res/layout/activity_tv.xml
@@ -23,33 +23,11 @@
     android:foreground="@android:color/transparent"
     android:keepScreenOn="true">
 
-    <com.android.tv.ui.AppLayerTvView android:id="@+id/main_tv_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_gravity="start|center_vertical" />
-
     <com.android.tv.ui.TunableTvView android:id="@+id/main_tunable_tv_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:layout_gravity="start|center_vertical" />
 
-    <com.android.tv.ui.AppLayerTvView android:id="@+id/pip_tv_view"
-        android:layout_marginLeft="@dimen/pipview_margin_horizontal"
-        android:layout_marginRight="@dimen/pipview_margin_horizontal"
-        android:layout_marginTop="@dimen/pipview_margin_top"
-        android:layout_marginBottom="@dimen/pipview_margin_bottom"
-        android:layout_width="@dimen/pipview_small_size_width"
-        android:layout_height="@dimen/pipview_small_size_height" />
-
-    <com.android.tv.ui.TunableTvView android:id="@+id/pip_tunable_tv_view"
-        android:visibility="gone"
-        android:layout_marginLeft="@dimen/pipview_margin_horizontal"
-        android:layout_marginRight="@dimen/pipview_margin_horizontal"
-        android:layout_marginTop="@dimen/pipview_margin_top"
-        android:layout_marginBottom="@dimen/pipview_margin_bottom"
-        android:layout_width="@dimen/pipview_small_size_width"
-        android:layout_height="@dimen/pipview_small_size_height" />
-
     <FrameLayout
         android:id="@+id/scene_container"
         android:layout_height="match_parent"
diff --git a/res/layout/block_screen.xml b/res/layout/block_screen.xml
index 6a04e96..c564efd 100644
--- a/res/layout/block_screen.xml
+++ b/res/layout/block_screen.xml
@@ -16,12 +16,18 @@
   -->
 
 <com.android.tv.ui.BlockScreenView xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:gravity="center"
     android:visibility="gone"
     android:background="@android:color/black">
+
+    <ImageView
+        android:id="@+id/background_image"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:scaleType="fitCenter"
+        android:visibility="gone" />
+
     <!-- This layout is used for the animation -->
     <LinearLayout
         android:id="@+id/block_screen_container"
@@ -43,6 +49,7 @@
                 android:contentDescription="@null" />
             <ImageView
                 android:id="@+id/block_screen_shrunken_icon"
+                android:src="@drawable/ic_message_lock_preview"
                 android:layout_width="@dimen/shrunken_tvview_block_icon_width"
                 android:layout_height="@dimen/shrunken_tvview_block_icon_height"
                 android:layout_gravity="center"
diff --git a/res/layout/dvr_details_description.xml b/res/layout/dvr_details_description.xml
index c5db470..d55688b 100644
--- a/res/layout/dvr_details_description.xml
+++ b/res/layout/dvr_details_description.xml
@@ -40,8 +40,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:orientation="vertical"
-        android:background="?android:attr/selectableItemBackground"
-        android:clickable="true">
+        android:background="?android:attr/selectableItemBackground">
 
         <TextView android:id="@+id/dvr_details_description_body"
             android:layout_width="wrap_content"
diff --git a/res/layout/dvr_main.xml b/res/layout/dvr_main.xml
index bac1cc9..6e18a83 100644
--- a/res/layout/dvr_main.xml
+++ b/res/layout/dvr_main.xml
@@ -16,6 +16,6 @@
   -->
 <fragment xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/dvr_frame"
-    android:name="com.android.tv.dvr.ui.DvrBrowseFragment"
+    android:name="com.android.tv.dvr.ui.browse.DvrBrowseFragment"
     android:layout_width="match_parent"
     android:layout_height="match_parent" />
\ No newline at end of file
diff --git a/res/layout/dvr_play.xml b/res/layout/dvr_play.xml
deleted file mode 100644
index 4df1368..0000000
--- a/res/layout/dvr_play.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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
-  -->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="match_parent">
-    <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:text="@string/no_program_information"
-            android:id="@+id/placeHolderText" android:layout_gravity="center"/>
-</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/dvr_recording_card_view.xml b/res/layout/dvr_recording_card_view.xml
index d3808a3..53a7cf3 100644
--- a/res/layout/dvr_recording_card_view.xml
+++ b/res/layout/dvr_recording_card_view.xml
@@ -16,12 +16,12 @@
 
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tv="http://schemas.android.com/apk/res/com.android.tv"
-    android:layout_width="@dimen/dvr_card_layout_width"
+    android:layout_width="wrap_content"
     android:layout_height="wrap_content">
 
     <FrameLayout
-        android:layout_width="@dimen/dvr_card_image_layout_width"
-        android:layout_height="@dimen/dvr_card_image_layout_height"
+        android:layout_width="@dimen/dvr_library_card_image_layout_width"
+        android:layout_height="@dimen/dvr_library_card_image_layout_height"
         android:layout_margin="2dp">
 
         <ImageView android:id="@+id/image"
@@ -35,7 +35,7 @@
         <ProgressBar android:id="@+id/recording_progress"
             style="@android:style/Widget.ProgressBar.Horizontal"
             android:layout_width="match_parent"
-            android:layout_height="@dimen/dvr_card_progress_height"
+            android:layout_height="@dimen/dvr_library_card_progress_height"
             android:mirrorForRtl="false"
             android:progressTint="@color/play_controls_progress_bar_watched"
             android:progressDrawable="@drawable/progress_horizontal"
@@ -70,13 +70,30 @@
         android:background="@color/dvr_card_info"
         tv:layout_viewType="info">
 
-        <TextView android:id="@+id/title"
+        <FrameLayout android:id="@+id/title_area"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginBottom="1dp"
-            android:gravity="start"
-            style="@style/dvr_card_view_title_text"
-            tv:layout_viewType="main"/>
+            android:layout_height="@dimen/dvr_library_card_folded_title_height">
+
+            <TextView android:id="@+id/title_one_line"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="1dp"
+                android:gravity="start"
+                android:maxLines="1"
+                style="@style/dvr_card_view_title_text"
+                tv:layout_viewType="main"/>
+
+            <TextView android:id="@+id/title_two_lines"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="1dp"
+                android:gravity="start"
+                android:maxLines="2"
+                android:alpha="0"
+                style="@style/dvr_card_view_title_text"
+                tv:layout_viewType="main"/>
+
+        </FrameLayout>
 
         <RelativeLayout
             android:layout_width="match_parent"
diff --git a/res/layout/dvr_schedules_item.xml b/res/layout/dvr_schedules_item.xml
index 1d97cb9..90e1123 100644
--- a/res/layout/dvr_schedules_item.xml
+++ b/res/layout/dvr_schedules_item.xml
@@ -44,19 +44,23 @@
             android:layout_height="match_parent"
             android:alpha="0"/>
 
+        <!-- Make parent focusable in case when the info_container is not focusable.
+             As the actions are GONE when the row is not selected, if info_container is not
+             focusable, there are no focusable views in the row, which causes that the row can't be
+             selected by the DPAD. To avoid this case, the parent should be focusable. -->
         <LinearLayout
             android:orientation="horizontal"
             android:layout_width="match_parent"
-            android:layout_height="match_parent">
+            android:layout_height="match_parent"
+            android:focusable="true"
+            android:descendantFocusability="afterDescendants">
 
             <LinearLayout android:id="@+id/info_container"
                 android:layout_width="0dp"
                 android:layout_height="match_parent"
                 android:layout_marginEnd="@dimen/dvr_schedules_item_section_margin"
                 android:layout_weight="1"
-                android:clickable="true"
-                android:focusableInTouchMode="true"
-                android:focusable="true">
+                android:clickable="true">
 
                 <TextView android:id="@+id/time"
                     android:layout_width="@dimen/dvr_schedules_item_time_width"
diff --git a/res/layout/guided_action_editable.xml b/res/layout/guided_action_editable.xml
new file mode 100644
index 0000000..84f56f8
--- /dev/null
+++ b/res/layout/guided_action_editable.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2017 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.
+  -->
+
+<android.support.v17.leanback.widget.GuidedActionItemContainer
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/guidedactions_editable"
+    style="?attr/guidedActionItemContainerStyle"
+    android:layout_height="88dp">
+
+    <android.support.v17.leanback.widget.NonOverlappingLinearLayout
+        android:id="@+id/guidedactions_item_content"
+        style="?attr/guidedActionItemContentStyle" >
+
+        <EditText
+            android:id="@+id/guidedactions_item_title"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:textColor="@color/lb_guidedactions_item_unselected_text_color"
+            android:textSize="16sp" />
+
+        <android.support.v17.leanback.widget.GuidedActionEditText
+            android:id="@+id/guidedactions_item_description"
+            style="?attr/guidedActionItemDescriptionStyle" />
+
+    </android.support.v17.leanback.widget.NonOverlappingLinearLayout>
+
+</android.support.v17.leanback.widget.GuidedActionItemContainer>
\ No newline at end of file
diff --git a/res/layout/input_banner.xml b/res/layout/input_banner.xml
index cd8770c..f4035fc 100644
--- a/res/layout/input_banner.xml
+++ b/res/layout/input_banner.xml
@@ -34,6 +34,7 @@
     <TextView android:id="@+id/input_label"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:maxWidth="@dimen/input_banner_item_label_max_width"
         android:fontFamily="@string/condensed_font"
         android:textColor="@color/select_input_text_color_primary"
         android:singleLine="true"
@@ -44,6 +45,7 @@
         android:layout_marginStart="16dp"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:maxWidth="@dimen/input_banner_item_label_max_width"
         android:fontFamily="@string/condensed_font"
         android:textColor="@color/select_input_text_color_secondary"
         android:singleLine="true"
diff --git a/res/layout/list_item_dvr_history.xml b/res/layout/list_item_dvr_history.xml
new file mode 100644
index 0000000..a9eb4c0
--- /dev/null
+++ b/res/layout/list_item_dvr_history.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:padding="2dp" >
+
+    <TextView
+        android:id="@+id/state"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="4dp"
+        android:paddingEnd="0dp" />
+
+    <TextView
+        android:id="@+id/schedule_time"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="4dp"
+        android:paddingEnd="0dp" />
+
+    <TextView
+        android:id="@+id/program_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="4dp"
+        android:paddingEnd="0dp" />
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="4dp"
+        android:paddingEnd="0dp"
+        android:text="@string/dvr_schedules_information_separator" />
+
+    <TextView
+        android:id="@+id/channel_name"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingStart="4dp"
+        android:paddingEnd="0dp" />
+
+</LinearLayout>
diff --git a/res/layout/menu_card_action.xml b/res/layout/menu_card_action.xml
index f17c5b6..e8114b5 100644
--- a/res/layout/menu_card_action.xml
+++ b/res/layout/menu_card_action.xml
@@ -19,50 +19,43 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="@dimen/action_card_width"
     android:layout_height="@dimen/action_card_height"
-    android:orientation="vertical"
     android:focusable="true"
     android:background="@drawable/action_card_background">
 
-    <LinearLayout
-        android:orientation="vertical"
+    <TextView
+        android:id="@+id/action_card_label"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:padding="@dimen/action_card_padding"
-        android:clipChildren="false"
-        android:clipToPadding="false"
-        android:layout_gravity="top">
+        android:layout_alignParentTop="true"
+        android:layout_marginStart="12dp"
+        android:layout_marginEnd="12dp"
+        android:layout_marginTop="6dp"
+        android:fontFamily="@string/condensed_font"
+        android:maxLines="1"
+        android:textColor="@color/action_card_label_color"
+        android:textSize="@dimen/action_card_label_font_size" />
 
-        <TextView
-            android:id="@+id/action_card_label"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="-6dp"
-            android:singleLine="true"
-            android:fontFamily="@string/condensed_font"
-            android:textColor="@color/action_card_label_color"
-            android:textSize="@dimen/action_card_label_font_size" />
-
-        <TextView
-            android:id="@+id/action_card_state"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingTop="4dp"
-            android:singleLine="true"
-            android:fontFamily="@string/condensed_font"
-            android:textColor="@color/action_card_state_color"
-            android:textSize="@dimen/action_card_state_font_size" />
-
-    </LinearLayout>
+    <TextView
+        android:id="@+id/action_card_state"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/action_card_label"
+        android:layout_marginStart="12dp"
+        android:layout_marginEnd="12dp"
+        android:paddingTop="4dp"
+        android:fontFamily="@string/condensed_font"
+        android:maxLines="1"
+        android:textColor="@color/action_card_state_color"
+        android:textSize="@dimen/action_card_state_font_size" />
 
     <ImageView
         android:id="@+id/action_card_icon"
         android:layout_width="@dimen/action_card_icon_width"
         android:layout_height="@dimen/action_card_icon_height"
         android:layout_margin="@dimen/action_card_icon_padding"
-        android:layout_gravity="end|bottom"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentEnd="true"
         android:contentDescription="@null"
-        android:scaleType="fitCenter"
-        android:src="@drawable/ic_tvoption_aspect"
-        android:duplicateParentState="true" />
+        android:scaleType="fitCenter" />
 
 </com.android.tv.menu.ActionCardView>
diff --git a/res/layout/menu_card_app_link.xml b/res/layout/menu_card_app_link.xml
index 918cb78..a7e3bd4 100644
--- a/res/layout/menu_card_app_link.xml
+++ b/res/layout/menu_card_app_link.xml
@@ -33,13 +33,6 @@
             android:layout_gravity="top"
             android:scaleType="centerCrop"/>
 
-        <View android:id="@+id/image_gradient"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center_horizontal"
-            android:background="@drawable/card_image_gradient"
-            android:visibility="gone" />
-
         <TextView android:id="@+id/app_info"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
diff --git a/res/layout/menu_card_channel.xml b/res/layout/menu_card_channel.xml
index 4e49636..ed7b827 100644
--- a/res/layout/menu_card_channel.xml
+++ b/res/layout/menu_card_channel.xml
@@ -32,13 +32,6 @@
             android:layout_gravity="top"
             android:scaleType="centerCrop"/>
 
-        <View android:id="@+id/image_gradient"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="center_horizontal"
-            android:background="@drawable/card_image_gradient"
-            android:visibility="gone" />
-
         <!-- The bottom margin specified in the redline is 8dp, but the redline doesn't consider
              the descenders. So actually, if the bottom margin is set to 8dp, the bottom line of
              the text lies 11dp above the bottom of the poster art due to the descenders.
diff --git a/res/layout/menu_card_dvr.xml b/res/layout/menu_card_dvr.xml
index cc58977..4f15908 100644
--- a/res/layout/menu_card_dvr.xml
+++ b/res/layout/menu_card_dvr.xml
@@ -23,17 +23,15 @@
     android:focusable="true"
     android:clickable="true">
 
-    <FrameLayout
+    <ImageView
         android:layout_width="@dimen/card_image_layout_width"
         android:layout_height="@dimen/card_image_layout_height"
-        android:background="@color/channel_card_guide">
-        <ImageView
-            android:layout_width="82dp"
-            android:layout_height="48dp"
-            android:layout_marginTop="16dp"
-            android:src="@drawable/ic_dvr"
-            android:layout_gravity="center_horizontal" />
-    </FrameLayout>
+        android:background="@color/channel_card_guide"
+        android:paddingBottom="16dp"
+        android:paddingEnd="30dp"
+        android:paddingStart="30dp"
+        android:paddingTop="16dp"
+        android:src="@drawable/ic_dvr" />
 
     <FrameLayout
         android:layout_width="match_parent"
diff --git a/res/layout/menu_card_guide.xml b/res/layout/menu_card_guide.xml
index 6b724b1..c36b7df 100644
--- a/res/layout/menu_card_guide.xml
+++ b/res/layout/menu_card_guide.xml
@@ -23,17 +23,15 @@
     android:focusable="true"
     android:clickable="true">
 
-    <FrameLayout
+    <ImageView
         android:layout_width="@dimen/card_image_layout_width"
         android:layout_height="@dimen/card_image_layout_height"
-        android:background="@color/channel_card_guide">
-        <ImageView
-            android:layout_width="82dp"
-            android:layout_height="48dp"
-            android:layout_marginTop="16dp"
-            android:src="@drawable/ic_channel_guide"
-            android:layout_gravity="center_horizontal" />
-    </FrameLayout>
+        android:background="@color/channel_card_guide"
+        android:paddingBottom="16dp"
+        android:paddingEnd="30dp"
+        android:paddingStart="30dp"
+        android:paddingTop="16dp"
+        android:src="@drawable/ic_channel_guide" />
 
     <TextView
         android:layout_width="match_parent"
diff --git a/res/layout/menu_card_setup.xml b/res/layout/menu_card_setup.xml
index 38abd4e..520cb4e 100644
--- a/res/layout/menu_card_setup.xml
+++ b/res/layout/menu_card_setup.xml
@@ -22,17 +22,15 @@
     android:focusable="true"
     android:clickable="true">
 
-    <FrameLayout
+    <ImageView
         android:layout_width="@dimen/card_image_layout_width"
         android:layout_height="@dimen/card_image_layout_height"
-        android:background="@color/channel_card_guide">
-        <ImageView
-            android:layout_width="82dp"
-            android:layout_height="48dp"
-            android:layout_marginTop="16dp"
-            android:src="@drawable/ic_setup_channels"
-            android:layout_gravity="center_horizontal" />
-    </FrameLayout>
+        android:background="@color/channel_card_guide"
+        android:paddingBottom="16dp"
+        android:paddingEnd="30dp"
+        android:paddingStart="30dp"
+        android:paddingTop="16dp"
+        android:src="@drawable/ic_setup_channels" />
 
     <TextView
         android:layout_width="match_parent"
diff --git a/res/layout/menu_card_text.xml b/res/layout/menu_card_text.xml
index 777b100..7674f81 100644
--- a/res/layout/menu_card_text.xml
+++ b/res/layout/menu_card_text.xml
@@ -16,7 +16,6 @@
   -->
 
 <merge xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tv="http://schemas.android.com/apk/res/com.android.tv"
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
diff --git a/res/layout/option_container.xml b/res/layout/option_container.xml
index f053e66..dd8c96c 100644
--- a/res/layout/option_container.xml
+++ b/res/layout/option_container.xml
@@ -22,6 +22,8 @@
     android:layout_gravity="end"
     android:elevation="@dimen/side_panel_elevation"
     android:background="@color/side_panel_background"
+    android:translationX="@dimen/side_panel_enter_offset_x"
+    android:alpha="0.0"
     android:visibility="gone">
 
     <!-- Background for header -->
diff --git a/res/layout/option_fragment.xml b/res/layout/option_fragment.xml
index 39f6749..4a4cbbd 100644
--- a/res/layout/option_fragment.xml
+++ b/res/layout/option_fragment.xml
@@ -41,7 +41,6 @@
         android:clipChildren="false"
         android:clipToPadding="false"
         android:focusable="true"
-        android:paddingTop="@dimen/side_panel_list_padding_top"
         android:paddingBottom="@dimen/side_panel_list_padding_bottom"
         lb:verticalMargin="@dimen/side_panel_list_vertical_margin" />
 
diff --git a/res/layout/option_item_action.xml b/res/layout/option_item_action.xml
index a7a02b2..6dc5b35 100644
--- a/res/layout/option_item_action.xml
+++ b/res/layout/option_item_action.xml
@@ -24,19 +24,8 @@
     android:focusable="true"
     android:background="?android:attr/selectableItemBackground" >
 
-    <ImageView
-        android:id="@+id/icon"
-        android:layout_width="36dp"
-        android:layout_height="36dp"
-        android:layout_weight="0"
-        android:layout_marginEnd="20dp"
-        android:layout_marginTop="14dp"
-        android:layout_marginBottom="14dp"
-        android:contentDescription="@null" />
-
     <include layout="@layout/option_item_common"
-        android:layout_width="0dp"
-        android:layout_height="match_parent"
-        android:layout_weight="1" />
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
 
 </LinearLayout>
diff --git a/res/layout/option_item_channel_check.xml b/res/layout/option_item_channel_check.xml
index 2817d2b..f68c2f9 100644
--- a/res/layout/option_item_channel_check.xml
+++ b/res/layout/option_item_channel_check.xml
@@ -28,7 +28,6 @@
         android:id="@+id/check_box"
         android:layout_width="@dimen/option_item_compound_button_width"
         android:layout_height="match_parent"
-        android:layout_weight="0"
         android:background="@null"
         android:clickable="false" />
 
diff --git a/res/layout/option_item_channel_lock.xml b/res/layout/option_item_channel_lock.xml
index f4f65f9..f7b5c9e 100644
--- a/res/layout/option_item_channel_lock.xml
+++ b/res/layout/option_item_channel_lock.xml
@@ -28,7 +28,6 @@
         android:id="@+id/check_box"
         android:layout_width="@dimen/option_item_compound_button_width"
         android:layout_height="match_parent"
-        android:layout_weight="0"
         android:button="@drawable/btn_lock_material_anim"
         android:background="@null"
         android:clickable="false" />
diff --git a/res/layout/option_item_check_box.xml b/res/layout/option_item_check_box.xml
index 1ab2ba4..711e362 100644
--- a/res/layout/option_item_check_box.xml
+++ b/res/layout/option_item_check_box.xml
@@ -28,7 +28,6 @@
         android:id="@+id/check_box"
         android:layout_width="@dimen/option_item_compound_button_width"
         android:layout_height="wrap_content"
-        android:layout_weight="0"
         android:layout_gravity="center"
         android:background="@null"
         android:clickable="false" />
diff --git a/res/layout/option_item_common.xml b/res/layout/option_item_common.xml
index ca0013c..6529421 100644
--- a/res/layout/option_item_common.xml
+++ b/res/layout/option_item_common.xml
@@ -42,7 +42,7 @@
         android:fontFamily="@string/option_item_secondary_text_font"
         android:textSize="@dimen/option_item_secondary_text_size"
         android:textColor="@color/option_item_secondary_text_color"
-        android:maxLines="3"
+        android:maxLines="@integer/option_item_description_max_lines"
         android:ellipsize="end"
         android:focusable="false" />
 
diff --git a/res/layout/option_item_radio_button.xml b/res/layout/option_item_radio_button.xml
index 2e4fa11..35be8c7 100644
--- a/res/layout/option_item_radio_button.xml
+++ b/res/layout/option_item_radio_button.xml
@@ -28,7 +28,6 @@
         android:id="@+id/radio_button"
         android:layout_width="@dimen/option_item_compound_button_width"
         android:layout_height="match_parent"
-        android:layout_weight="0"
         android:background="@null"
         android:clickable="false" />
 
diff --git a/res/layout/option_item_switch.xml b/res/layout/option_item_switch.xml
index 4750ebc..7b5c6ec 100644
--- a/res/layout/option_item_switch.xml
+++ b/res/layout/option_item_switch.xml
@@ -33,7 +33,6 @@
         android:id="@+id/switch_button"
         android:layout_width="@dimen/option_item_compound_button_width"
         android:layout_height="match_parent"
-        android:layout_weight="0"
         android:background="@null"
         android:clickable="false" />
 
diff --git a/res/layout/play_controls_contents.xml b/res/layout/play_controls_contents.xml
index ac61a2d..9afc5f3 100644
--- a/res/layout/play_controls_contents.xml
+++ b/res/layout/play_controls_contents.xml
@@ -16,6 +16,7 @@
   -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/play_controls"
     style="@style/menu_row_contents_view"
     android:layoutDirection="ltr">
@@ -28,153 +29,118 @@
         android:layout_alignStart="@+id/body"
         android:layout_marginBottom="@dimen/play_controls_time_bottom_margin"
         android:gravity="center"
-        android:singleLine="true"
+        android:maxLines="1"
         android:textColor="@color/play_controls_time_text_color"
         android:textSize="@dimen/play_controls_time_text_size"
         android:fontFamily="@string/font" />
 
-    <LinearLayout
+    <RelativeLayout
         android:id="@id/body"
-        android:orientation="vertical"
         android:layout_width="@dimen/play_controls_width"
         android:layout_height="wrap_content"
         android:layout_below="@id/time_text"
         android:layout_centerHorizontal="true"
         android:background="@drawable/play_controls_body_shape">
 
-        <RelativeLayout
+        <com.android.tv.menu.PlaybackProgressBar
+            android:id="@+id/progress"
             android:layout_width="match_parent"
-            android:layout_height="@dimen/play_controls_progress_height">
-
-            <ImageView
-                android:id="@+id/timeline_bg_start"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_alignParentStart="true"
-                android:src="@color/play_controls_progress_bar_background" />
-            <ImageView
-                android:id="@+id/watched"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_toEndOf="@id/timeline_bg_start"
-                android:src="@color/play_controls_progress_bar_watched" />
-            <ImageView
-                android:id="@+id/buffered"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_toEndOf="@id/watched"
-                android:src="@color/play_controls_progress_bar_buffered" />
-            <ImageView
-                android:id="@+id/timeline_bg_end"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:layout_alignParentEnd="true"
-                android:layout_toEndOf="@id/buffered"
-                android:src="@color/play_controls_progress_bar_background" />
-
-        </RelativeLayout>
-
-        <FrameLayout
+            android:layout_height="@dimen/play_controls_progress_height"
+            android:layout_alignParentTop="true"
+            tv:progressDrawable="@drawable/playback_progress_bar" />
+        <TextView
             android:id="@+id/background"
             android:layout_width="match_parent"
+            android:layout_height="@dimen/play_controls_button_height"
+            android:layout_below="@id/progress"
+            android:background="@drawable/play_controls_body_background"
+            android:gravity="center"
+            android:maxLines="1"
+            android:textColor="@color/play_controls_unavailable_message_text_color"
+            android:textSize="@dimen/play_controls_unavailable_message_text_size"
+            android:fontFamily="@string/font" />
+        <TextView
+            android:id="@+id/program_start_time"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:background="@drawable/play_controls_body_background">
+            android:layout_alignParentStart="true"
+            android:layout_below="@id/progress"
+            android:layout_marginStart="@dimen/play_controls_program_time_margin_start"
+            android:layout_marginTop="@dimen/play_controls_program_time_margin_top"
+            android:maxLines="1"
+            android:textColor="@color/play_controls_rec_time_text_color"
+            android:textSize="@dimen/play_controls_rec_time_text_size"
+            android:fontFamily="@string/font" />
+        <TextView
+            android:id="@+id/program_end_time"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentEnd="true"
+            android:layout_below="@id/progress"
+            android:layout_marginEnd="@dimen/play_controls_program_time_margin_end"
+            android:layout_marginTop="@dimen/play_controls_program_time_margin_top"
+            android:maxLines="1"
+            android:textColor="@color/play_controls_rec_time_text_color"
+            android:textSize="@dimen/play_controls_rec_time_text_size"
+            android:fontFamily="@string/font" />
 
-            <TextView
-                android:id="@+id/program_start_time"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginStart="@dimen/play_controls_program_time_margin_start"
-                android:layout_marginTop="@dimen/play_controls_program_time_margin_top"
-                android:singleLine="true"
-                android:textColor="@color/play_controls_rec_time_text_color"
-                android:textSize="@dimen/play_controls_rec_time_text_size"
-                android:fontFamily="@string/font" />
-            <TextView
-                android:id="@+id/program_end_time"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="@dimen/play_controls_program_time_margin_end"
-                android:layout_marginTop="@dimen/play_controls_program_time_margin_top"
-                android:layout_gravity="end"
-                android:singleLine="true"
-                android:textColor="@color/play_controls_rec_time_text_color"
-                android:textSize="@dimen/play_controls_rec_time_text_size"
-                android:fontFamily="@string/font" />
+        <com.android.tv.menu.PlayControlsButton
+            android:id="@+id/play_pause"
+            android:layout_width="@dimen/play_controls_button_width"
+            android:layout_height="@dimen/play_controls_button_height"
+            android:layout_below="@id/progress"
+            android:layout_marginLeft="@dimen/play_controls_button_compact_margin"
+            android:layout_marginRight="@dimen/play_controls_button_compact_margin"
+            android:layout_centerHorizontal="true" />
+        <com.android.tv.menu.PlayControlsButton
+            android:id="@+id/rewind"
+            android:layout_width="@dimen/play_controls_button_width"
+            android:layout_height="@dimen/play_controls_button_height"
+            android:layout_below="@id/progress"
+            android:layout_marginLeft="@dimen/play_controls_button_compact_margin"
+            android:layout_marginRight="@dimen/play_controls_button_compact_margin"
+            android:layout_toStartOf="@id/play_pause" />
+        <com.android.tv.menu.PlayControlsButton
+            android:id="@+id/jump_previous"
+            android:layout_width="@dimen/play_controls_button_width"
+            android:layout_height="@dimen/play_controls_button_height"
+            android:layout_below="@id/progress"
+            android:layout_marginLeft="@dimen/play_controls_button_compact_margin"
+            android:layout_marginRight="@dimen/play_controls_button_compact_margin"
+            android:layout_toStartOf="@id/rewind" />
+        <com.android.tv.menu.PlayControlsButton
+            android:id="@+id/fast_forward"
+            android:layout_width="@dimen/play_controls_button_width"
+            android:layout_height="@dimen/play_controls_button_height"
+            android:layout_below="@id/progress"
+            android:layout_marginLeft="@dimen/play_controls_button_compact_margin"
+            android:layout_marginRight="@dimen/play_controls_button_compact_margin"
+            android:layout_toEndOf="@id/play_pause" />
+        <com.android.tv.menu.PlayControlsButton
+            android:id="@+id/jump_next"
+            android:layout_width="@dimen/play_controls_button_width"
+            android:layout_height="@dimen/play_controls_button_height"
+            android:layout_below="@id/progress"
+            android:layout_marginLeft="@dimen/play_controls_button_compact_margin"
+            android:layout_marginRight="@dimen/play_controls_button_compact_margin"
+            android:layout_toEndOf="@id/fast_forward" />
+        <com.android.tv.menu.PlayControlsButton
+            android:id="@+id/record"
+            android:layout_width="@dimen/play_controls_button_width"
+            android:layout_height="@dimen/play_controls_button_height"
+            android:layout_below="@id/progress"
+            android:layout_marginLeft="@dimen/play_controls_button_compact_margin"
+            android:layout_marginRight="@dimen/play_controls_button_compact_margin"
+            android:layout_toEndOf="@id/jump_next" />
+    </RelativeLayout>
 
-            <RelativeLayout
-                android:id="@+id/play_control_bar"
-                android:layout_width="match_parent"
-                android:layout_height="@dimen/play_controls_button_height">
-
-                <com.android.tv.menu.PlayControlsButton
-                    android:id="@+id/play_pause"
-                    android:layout_width="@dimen/play_controls_button_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginLeft="@dimen/play_controls_button_normal_margin"
-                    android:layout_marginRight="@dimen/play_controls_button_normal_margin"
-                    android:layout_centerHorizontal="true" />
-                <com.android.tv.menu.PlayControlsButton
-                    android:id="@+id/rewind"
-                    android:layout_width="@dimen/play_controls_button_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginLeft="@dimen/play_controls_button_normal_margin"
-                    android:layout_marginRight="@dimen/play_controls_button_normal_margin"
-                    android:layout_toLeftOf="@id/play_pause" />
-                <com.android.tv.menu.PlayControlsButton
-                    android:id="@+id/jump_previous"
-                    android:layout_width="@dimen/play_controls_button_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginLeft="@dimen/play_controls_button_normal_margin"
-                    android:layout_marginRight="@dimen/play_controls_button_normal_margin"
-                    android:layout_toLeftOf="@id/rewind" />
-                <com.android.tv.menu.PlayControlsButton
-                    android:id="@+id/fast_forward"
-                    android:layout_width="@dimen/play_controls_button_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginLeft="@dimen/play_controls_button_normal_margin"
-                    android:layout_marginRight="@dimen/play_controls_button_normal_margin"
-                    android:layout_toRightOf="@id/play_pause" />
-                <com.android.tv.menu.PlayControlsButton
-                    android:id="@+id/jump_next"
-                    android:layout_width="@dimen/play_controls_button_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginLeft="@dimen/play_controls_button_normal_margin"
-                    android:layout_marginRight="@dimen/play_controls_button_normal_margin"
-                    android:layout_toRightOf="@id/fast_forward" />
-                <com.android.tv.menu.PlayControlsButton
-                    android:id="@+id/record"
-                    android:layout_width="@dimen/play_controls_button_width"
-                    android:layout_height="match_parent"
-                    android:layout_marginLeft="@dimen/play_controls_button_normal_margin"
-                    android:layout_marginRight="@dimen/play_controls_button_normal_margin"
-                    android:layout_toRightOf="@id/jump_next"
-                    android:visibility="gone" />
-
-            </RelativeLayout>
-
-            <TextView
-                android:id="@+id/unavailable_text"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:singleLine="true"
-                android:textColor="@color/play_controls_unavailable_message_text_color"
-                android:textSize="@dimen/play_controls_unavailable_message_text_size"
-                android:fontFamily="@string/font"
-                android:visibility="gone"
-                android:text="@string/play_controls_unavailable" />
-        </FrameLayout>
-    </LinearLayout>
-
-    <ImageView
+    <View
         android:id="@+id/time_indicator"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:layout_width="@dimen/play_controls_time_indicator_width"
+        android:layout_height="@dimen/play_controls_time_indicator_height"
         android:layout_marginTop="@dimen/play_controls_time_indicator_top_margin"
         android:layout_alignTop="@id/body"
         android:layout_alignStart="@id/body"
         android:background="@drawable/play_controls_time_indicator"
-        android:visibility="invisible"
         android:elevation="1dp" />
 </RelativeLayout>
diff --git a/res/layout/select_input_item.xml b/res/layout/select_input_item.xml
index 1ff6df2..12fedca 100644
--- a/res/layout/select_input_item.xml
+++ b/res/layout/select_input_item.xml
@@ -28,6 +28,7 @@
     <TextView android:id="@+id/input_label"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:maxWidth="@dimen/input_banner_item_label_max_width"
         android:fontFamily="@string/condensed_font"
         android:singleLine="true"
         android:ellipsize="end"
@@ -37,6 +38,7 @@
         android:layout_marginStart="16dp"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:maxWidth="@dimen/input_banner_item_label_max_width"
         android:fontFamily="@string/condensed_font"
         android:singleLine="true"
         android:ellipsize="end"
diff --git a/res/layout/tunable_tv_view.xml b/res/layout/tunable_tv_view.xml
index e02fb89..00c9908 100644
--- a/res/layout/tunable_tv_view.xml
+++ b/res/layout/tunable_tv_view.xml
@@ -16,15 +16,14 @@
   -->
 
 <merge xmlns:android="http://schemas.android.com/apk/res/android" >
-    <View
-        android:id="@+id/block_screen_for_tune"
-        android:visibility="gone"
+
+    <com.android.tv.ui.AppLayerTvView android:id="@+id/tv_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@android:color/black" />
+        android:layout_gravity="start|center_vertical" />
 
     <include layout="@layout/block_screen"
-        android:id="@+id/hide_screen" />
+        android:id="@+id/block_screen" />
 
     <ProgressBar
         android:id="@+id/buffering_spinner"
@@ -34,11 +33,8 @@
         android:background="@android:color/transparent"
         android:layout_gravity="center" />
 
-    <include layout="@layout/block_screen"
-        android:id="@+id/block_screen" />
-
     <View
-        android:id="@+id/dim"
+        android:id="@+id/dim_screen"
         android:visibility="gone"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/res/raw/third_party_license_metadata b/res/raw/third_party_license_metadata
new file mode 100755
index 0000000..4a31b62
--- /dev/null
+++ b/res/raw/third_party_license_metadata
@@ -0,0 +1,21 @@
+19:1096 Animal Sniffer
+1140:11358 Apache Commons Codec
+12514:11357 Error Prone
+23885:11358 ExoPlayer
+35266:11358 FasterXML Jackson2
+46640:11358 Google Auto
+58013:11358 Guava JDK5
+69386:11362 Guava JDK7
+80759:11358 J2ObjC
+92129:11358 JSR 250
+103498:11358 OkHttp
+114865:11358 Okio
+126232:10402 gRPC
+136654:11358 instrumentation
+148036:1473 Auth client library
+149521:1602 JSR 305
+151136:1732 Protobuf
+152886:1732 Protobuf Nano
+154631:1561 minijail
+156203:26427 ffmpeg
+182640:19442 icu4j
diff --git a/res/raw/third_party_licenses b/res/raw/third_party_licenses
new file mode 100755
index 0000000..96227dc
--- /dev/null
+++ b/res/raw/third_party_licenses
@@ -0,0 +1,3751 @@
+
+
+Animal Sniffer:
+
+The MIT License
+
+Copyright (c) 2008 Kohsuke Kawaguchi and codehaus.org.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+
+Apache Commons Codec:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+Error Prone:
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+ExoPlayer:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+FasterXML Jackson2:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+Google Auto:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+Guava JDK5:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+Guava JDK7:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+   
+
+
+J2ObjC:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+JSR 250:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+OkHttp:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+Okio:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+gRPC:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        https://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for any such Derivative Works as a whole, provided Your use,
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   Copyright 2015-2017 gRPC authors.
+
+   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
+
+       https://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.
+
+
+instrumentation:
+
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+Auth client library:
+
+Copyright 2014, Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+JSR 305:
+
+Copyright (c) 2007-2009, JSR305 expert group
+All rights reserved.
+
+http://www.opensource.org/licenses/bsd-license.php
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, 
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice, 
+      this list of conditions and the following disclaimer in the documentation 
+      and/or other materials provided with the distribution.
+    * Neither the name of the JSR305 expert group nor the names of its 
+      contributors may be used to endorse or promote products derived from 
+      this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+POSSIBILITY OF SUCH DAMAGE.
+
+
+Protobuf:
+
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Code generated by the Protocol Buffer compiler is owned by the owner
+of the input file used when generating it.  This code is not
+standalone and requires a support library to be linked with it.  This
+support library is itself covered by the above license.
+
+
+Protobuf Nano:
+
+Copyright 2008, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+    * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Code generated by the Protocol Buffer compiler is owned by the owner
+of the input file used when generating it.  This code is not
+standalone and requires a support library to be linked with it.  This
+support library is itself covered by the above license.
+
+
+minijail:
+
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ffmpeg:
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+
+
+icu4j:
+
+COPYRIGHT AND PERMISSION NOTICE (ICU 58 and later)
+
+Copyright © 1991-2016 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in http://www.unicode.org/copyright.html
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that either
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software, or
+(b) this copyright and permission notice appear in associated
+Documentation.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+
+---------------------
+
+Third-Party Software Licenses
+
+This section contains third-party software notices and/or additional
+terms for licensed third-party software components included within ICU
+libraries.
+
+1. ICU License - ICU 1.8.1 to ICU 57.1
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright (c) 1995-2016 International Business Machines Corporation and others
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, and/or sell copies of the Software, and to permit persons
+to whom the Software is furnished to do so, provided that the above
+copyright notice(s) and this permission notice appear in all copies of
+the Software and that both the above copyright notice(s) and this
+permission notice appear in supporting documentation.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY
+SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER
+RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale, use
+or other dealings in this Software without prior written authorization
+of the copyright holder.
+
+All trademarks and registered trademarks mentioned herein are the
+property of their respective owners.
+
+2. Chinese/Japanese Word Break Dictionary Data (cjdict.txt)
+
+ #     The Google Chrome software developed by Google is licensed under
+ # the BSD license. Other software included in this distribution is
+ # provided under other licenses, as set forth below.
+ #
+ #  The BSD License
+ #  http://opensource.org/licenses/bsd-license.php
+ #  Copyright (C) 2006-2008, Google Inc.
+ #
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ # modification, are permitted provided that the following conditions are met:
+ #
+ #  Redistributions of source code must retain the above copyright notice,
+ # this list of conditions and the following disclaimer.
+ #  Redistributions in binary form must reproduce the above
+ # copyright notice, this list of conditions and the following
+ # disclaimer in the documentation and/or other materials provided with
+ # the distribution.
+ #  Neither the name of  Google Inc. nor the names of its
+ # contributors may be used to endorse or promote products derived from
+ # this software without specific prior written permission.
+ #
+ #
+ #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ # CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ # BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ #
+ #
+ #  The word list in cjdict.txt are generated by combining three word lists
+ # listed below with further processing for compound word breaking. The
+ # frequency is generated with an iterative training against Google web
+ # corpora.
+ #
+ #  * Libtabe (Chinese)
+ #    - https://sourceforge.net/project/?group_id=1519
+ #    - Its license terms and conditions are shown below.
+ #
+ #  * IPADIC (Japanese)
+ #    - http://chasen.aist-nara.ac.jp/chasen/distribution.html
+ #    - Its license terms and conditions are shown below.
+ #
+ #  ---------COPYING.libtabe ---- BEGIN--------------------
+ #
+ #  /*
+ #   * Copyrighy (c) 1999 TaBE Project.
+ #   * Copyright (c) 1999 Pai-Hsiang Hsiao.
+ #   * All rights reserved.
+ #   *
+ #   * Redistribution and use in source and binary forms, with or without
+ #   * modification, are permitted provided that the following conditions
+ #   * are met:
+ #   *
+ #   * . Redistributions of source code must retain the above copyright
+ #   *   notice, this list of conditions and the following disclaimer.
+ #   * . Redistributions in binary form must reproduce the above copyright
+ #   *   notice, this list of conditions and the following disclaimer in
+ #   *   the documentation and/or other materials provided with the
+ #   *   distribution.
+ #   * . Neither the name of the TaBE Project nor the names of its
+ #   *   contributors may be used to endorse or promote products derived
+ #   *   from this software without specific prior written permission.
+ #   *
+ #   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ #   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ #   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ #   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ #   * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ #   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ #   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ #   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ #   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ #   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ #   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ #   * OF THE POSSIBILITY OF SUCH DAMAGE.
+ #   */
+ #
+ #  /*
+ #   * Copyright (c) 1999 Computer Systems and Communication Lab,
+ #   *                    Institute of Information Science, Academia
+ #       *                    Sinica. All rights reserved.
+ #   *
+ #   * Redistribution and use in source and binary forms, with or without
+ #   * modification, are permitted provided that the following conditions
+ #   * are met:
+ #   *
+ #   * . Redistributions of source code must retain the above copyright
+ #   *   notice, this list of conditions and the following disclaimer.
+ #   * . Redistributions in binary form must reproduce the above copyright
+ #   *   notice, this list of conditions and the following disclaimer in
+ #   *   the documentation and/or other materials provided with the
+ #   *   distribution.
+ #   * . Neither the name of the Computer Systems and Communication Lab
+ #   *   nor the names of its contributors may be used to endorse or
+ #   *   promote products derived from this software without specific
+ #   *   prior written permission.
+ #   *
+ #   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ #   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ #   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ #   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ #   * REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ #   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ #   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ #   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ #   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ #   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ #   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ #   * OF THE POSSIBILITY OF SUCH DAMAGE.
+ #   */
+ #
+ #  Copyright 1996 Chih-Hao Tsai @ Beckman Institute,
+ #      University of Illinois
+ #  c-tsai4@uiuc.edu  http://casper.beckman.uiuc.edu/~c-tsai4
+ #
+ #  ---------------COPYING.libtabe-----END--------------------------------
+ #
+ #
+ #  ---------------COPYING.ipadic-----BEGIN-------------------------------
+ #
+ #  Copyright 2000, 2001, 2002, 2003 Nara Institute of Science
+ #  and Technology.  All Rights Reserved.
+ #
+ #  Use, reproduction, and distribution of this software is permitted.
+ #  Any copy of this software, whether in its original form or modified,
+ #  must include both the above copyright notice and the following
+ #  paragraphs.
+ #
+ #  Nara Institute of Science and Technology (NAIST),
+ #  the copyright holders, disclaims all warranties with regard to this
+ #  software, including all implied warranties of merchantability and
+ #  fitness, in no event shall NAIST be liable for
+ #  any special, indirect or consequential damages or any damages
+ #  whatsoever resulting from loss of use, data or profits, whether in an
+ #  action of contract, negligence or other tortuous action, arising out
+ #  of or in connection with the use or performance of this software.
+ #
+ #  A large portion of the dictionary entries
+ #  originate from ICOT Free Software.  The following conditions for ICOT
+ #  Free Software applies to the current dictionary as well.
+ #
+ #  Each User may also freely distribute the Program, whether in its
+ #  original form or modified, to any third party or parties, PROVIDED
+ #  that the provisions of Section 3 ("NO WARRANTY") will ALWAYS appear
+ #  on, or be attached to, the Program, which is distributed substantially
+ #  in the same form as set out herein and that such intended
+ #  distribution, if actually made, will neither violate or otherwise
+ #  contravene any of the laws and regulations of the countries having
+ #  jurisdiction over the User or the intended distribution itself.
+ #
+ #  NO WARRANTY
+ #
+ #  The program was produced on an experimental basis in the course of the
+ #  research and development conducted during the project and is provided
+ #  to users as so produced on an experimental basis.  Accordingly, the
+ #  program is provided without any warranty whatsoever, whether express,
+ #  implied, statutory or otherwise.  The term "warranty" used herein
+ #  includes, but is not limited to, any warranty of the quality,
+ #  performance, merchantability and fitness for a particular purpose of
+ #  the program and the nonexistence of any infringement or violation of
+ #  any right of any third party.
+ #
+ #  Each user of the program will agree and understand, and be deemed to
+ #  have agreed and understood, that there is no warranty whatsoever for
+ #  the program and, accordingly, the entire risk arising from or
+ #  otherwise connected with the program is assumed by the user.
+ #
+ #  Therefore, neither ICOT, the copyright holder, or any other
+ #  organization that participated in or was otherwise related to the
+ #  development of the program and their respective officials, directors,
+ #  officers and other employees shall be held liable for any and all
+ #  damages, including, without limitation, general, special, incidental
+ #  and consequential damages, arising out of or otherwise in connection
+ #  with the use or inability to use the program or any product, material
+ #  or result produced or otherwise obtained by using the program,
+ #  regardless of whether they have been advised of, or otherwise had
+ #  knowledge of, the possibility of such damages at any time during the
+ #  project or thereafter.  Each user will be deemed to have agreed to the
+ #  foregoing by his or her commencement of use of the program.  The term
+ #  "use" as used herein includes, but is not limited to, the use,
+ #  modification, copying and distribution of the program and the
+ #  production of secondary products from the program.
+ #
+ #  In the case where the program, whether in its original form or
+ #  modified, was distributed or delivered to or received by a user from
+ #  any person, organization or entity other than ICOT, unless it makes or
+ #  grants independently of ICOT any specific warranty to the user in
+ #  writing, such person, organization or entity, will also be exempted
+ #  from and not be held liable to the user for any such damages as noted
+ #  above as far as the program is concerned.
+ #
+ #  ---------------COPYING.ipadic-----END----------------------------------
+
+3. Lao Word Break Dictionary Data (laodict.txt)
+
+ #  Copyright (c) 2013 International Business Machines Corporation
+ #  and others. All Rights Reserved.
+ #
+ # Project: http://code.google.com/p/lao-dictionary/
+ # Dictionary: http://lao-dictionary.googlecode.com/git/Lao-Dictionary.txt
+ # License: http://lao-dictionary.googlecode.com/git/Lao-Dictionary-LICENSE.txt
+ #              (copied below)
+ #
+ #  This file is derived from the above dictionary, with slight
+ #  modifications.
+ #  ----------------------------------------------------------------------
+ #  Copyright (C) 2013 Brian Eugene Wilson, Robert Martin Campbell.
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ #  modification,
+ #  are permitted provided that the following conditions are met:
+ #
+ #
+ # Redistributions of source code must retain the above copyright notice, this
+ #  list of conditions and the following disclaimer. Redistributions in
+ #  binary form must reproduce the above copyright notice, this list of
+ #  conditions and the following disclaimer in the documentation and/or
+ #  other materials provided with the distribution.
+ #
+ #
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ # OF THE POSSIBILITY OF SUCH DAMAGE.
+ #  --------------------------------------------------------------------------
+
+4. Burmese Word Break Dictionary Data (burmesedict.txt)
+
+ #  Copyright (c) 2014 International Business Machines Corporation
+ #  and others. All Rights Reserved.
+ #
+ #  This list is part of a project hosted at:
+ #    github.com/kanyawtech/myanmar-karen-word-lists
+ #
+ #  --------------------------------------------------------------------------
+ #  Copyright (c) 2013, LeRoy Benjamin Sharon
+ #  All rights reserved.
+ #
+ #  Redistribution and use in source and binary forms, with or without
+ #  modification, are permitted provided that the following conditions
+ #  are met: Redistributions of source code must retain the above
+ #  copyright notice, this list of conditions and the following
+ #  disclaimer.  Redistributions in binary form must reproduce the
+ #  above copyright notice, this list of conditions and the following
+ #  disclaimer in the documentation and/or other materials provided
+ #  with the distribution.
+ #
+ #    Neither the name Myanmar Karen Word Lists, nor the names of its
+ #    contributors may be used to endorse or promote products derived
+ #    from this software without specific prior written permission.
+ #
+ #  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ #  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ #  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ #  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ #  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
+ #  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ #  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ #  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ #  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ #  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ #  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ #  THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ #  SUCH DAMAGE.
+ #  --------------------------------------------------------------------------
+
+5. Time Zone Database
+
+  ICU uses the public domain data and code derived from Time Zone
+Database for its time zone support. The ownership of the TZ database
+is explained in BCP 175: Procedure for Maintaining the Time Zone
+Database section 7.
+
+ # 7.  Database Ownership
+ #
+ #    The TZ database itself is not an IETF Contribution or an IETF
+ #    document.  Rather it is a pre-existing and regularly updated work
+ #    that is in the public domain, and is intended to remain in the
+ #    public domain.  Therefore, BCPs 78 [RFC5378] and 79 [RFC3979] do
+ #    not apply to the TZ Database or contributions that individuals make
+ #    to it.  Should any claims be made and substantiated against the TZ
+ #    Database, the organization that is providing the IANA
+ #    Considerations defined in this RFC, under the memorandum of
+ #    understanding with the IETF, currently ICANN, may act in accordance
+ #    with all competent court orders.  No ownership claims will be made
+ #    by ICANN or the IETF Trust on the database or the code.  Any person
+ #    making a contribution to the database or code waives all rights to
+ #    future claims in that contribution or in the TZ Database.
diff --git a/res/transition/dvr_details_shared_element_enter_transition.xml b/res/transition/dvr_details_shared_element_enter_transition.xml
new file mode 100644
index 0000000..d3fc065
--- /dev/null
+++ b/res/transition/dvr_details_shared_element_enter_transition.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 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.
+-->
+
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tv="http://schemas.android.com/apk/res-auto">
+    <transition class="com.android.tv.dvr.ui.FadeBackground"
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="500"
+        tv:fadingMode="fade_in">
+        <targets>
+            <target android:targetId="@id/details_frame" />
+            <target android:targetId="@id/details_overview_image" />
+            <target android:targetId="@id/details_overview_right_panel" />
+        </targets>
+    </transition>
+    <!-- The followings are copied from lb_shared_element_enter_transiton.xml -->
+    <fade
+        android:fadingMode="fade_in"
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:startDelay="325"
+        android:duration="150"/>
+    <changeBounds
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="500"/>
+    <changeTransform
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="500"/>
+    <!-- TODO: Change this to changeImageTransform once b/32405620 is fixed. -->
+    <transition class="com.android.tv.dvr.ui.ChangeImageTransformWithScaledParent"
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="500"/>
+</transitionSet>
\ No newline at end of file
diff --git a/res/transition/dvr_details_shared_element_return_transition.xml b/res/transition/dvr_details_shared_element_return_transition.xml
new file mode 100644
index 0000000..ceabca4
--- /dev/null
+++ b/res/transition/dvr_details_shared_element_return_transition.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 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.
+-->
+
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tv="http://schemas.android.com/apk/res-auto">
+    <transition class="com.android.tv.dvr.ui.FadeBackground"
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="325"
+        tv:fadingMode="fade_out">
+        <targets>
+            <target android:targetId="@id/details_frame" />
+            <target android:targetId="@id/details_overview_image" />
+            <target android:targetId="@id/details_overview_right_panel" />
+        </targets>
+    </transition>
+    <!-- The followings are copied from lb_shared_element_return_transiton.xml -->
+    <fade
+        android:fadingMode="fade_out"
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="75"/>
+    <changeBounds
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="325"/>
+    <changeTransform
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="325"/>
+    <!-- TODO: Change this to changeImageTransofrm once b/32405620 is fixed. -->
+    <transition class="com.android.tv.dvr.ui.ChangeImageTransformWithScaledParent"
+        android:interpolator="@android:interpolator/linear_out_slow_in"
+        android:duration="325"/>
+</transitionSet>
\ No newline at end of file
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 7778e75..24d484d 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Speelkontroles"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Onlangse kanale"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanale"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV-opsies"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-opsies"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Speelkontroles onbeskikbaar vir hierdie kanaal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Speel of laat wag"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Vinnig vorentoe"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Onderskrifte"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Vertoonmodus"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Aan"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Af"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-oudio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Kry meer kanale"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Instellings"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Bron"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Ruil"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Aan"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Af"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Klank"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Hoof"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-venster"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Uitleg"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Regs onder"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Regs bo"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Links bo"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Links onder"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Langs mekaar"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Grootte"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Groot"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Klein"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Invoerbron"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenna/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Geen programinligting nie"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Geen inligting nie"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Geblokkeerde kanaal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Onbekende taal"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Onbekende taal"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Onderskrifte %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Onderskrifte"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Af"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Pasmaak formatering"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Groepeer volgens"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Hierdie program word geblokkeer"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Hierdie program is ongegradeer"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Hierdie program is <xliff:g id="RATING">%1$s</xliff:g> gegradeer"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Die invoer steun nie outoskandering nie"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Kan nie outoskandeer vir \'<xliff:g id="TV_INPUT">%s</xliff:g>\' begin nie"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d kanaal is bygevoeg</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Geen kanale bygevoeg nie"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Ontvanger"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Ouerkontroles"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Aan"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Af"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Ander lande"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Geen"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Geen"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Ongegradeer"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Keer ongegradeerde programme"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Geen"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Hoë beperkings"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Mediumbeperkings"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Voer jou PIN in om hierdie kanaal te kyk"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Voer jou PIN in om hierdie program te kyk"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Hierdie program is <xliff:g id="RATING">%1$s</xliff:g> gegradeer. Voer jou PIN in om hierdie program te kyk"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Hierdie program is ongegradeer. Voer jou PIN in om hierdie program te kyk"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Voer jou PIN in"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Skep \'n PIN om ouerkontroles op te stel"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Voer nuwe PIN in"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Die PIN is verkeerd. Probeer weer."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Probeer weer. PIN stem nie ooreen nie"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Voer jou poskode in."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Regstreekse kanale-program sal die poskode gebruik om \'n volledige programgids vir die TV-kanale te voorsien."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Voer jou poskode in"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Ongeldige poskode"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Instellings"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Pasmaak kanaallys"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Kies kanale vir jou programgids"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanaalbronne"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nuwe kanale beskikbaar"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Ouerkontroles"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Tydskuif"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Neem op terwyl jy kyk sodat jy regstreekse programme kan onderbreek of terugspeel.\nWaarskuwing: Dit kan die lewe van die interne berging deur die intensiewe gebruik van die berging verkort."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Oopbronlisensies"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Oopbronlisensies"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Stuur terugvoer"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Weergawe"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Druk Regs en voer jou PIN in om hierdie kanaal te kyk"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Druk Regs en voer jou PIN in om hierdie program te kyk"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Hierdie program is ongegradeer.\nDruk Regs en voer jou PIN in om hierdie program te kyk"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Hierdie program is <xliff:g id="RATING">%1$s</xliff:g> gegradeer.\nDruk Regs en voer jou PIN in om hierdie program te kyk."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Gebruik die verstekprogram vir Regstreekse TV om hierdie kanaal te kyk."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Gebruik die verstekprogram vir Regstreekse TV om hierdie program te kyk."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Hierdie program is ongegradeer.\nGebruik die verstekprogram vir Regstreekse TV om hierdie program te kyk."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Hierdie program is <xliff:g id="RATING">%1$s</xliff:g> gegradeer.\nGebruik die verstekprogram vir Regstreekse TV om hierdie kanaal te kyk."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Program is geblokkeer"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Hierdie program is ongegradeer"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Hierdie program is <xliff:g id="RATING">%1$s</xliff:g> gegradeer"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Net oudio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Swak sein"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Druk KIES"</b>" om na die TV-kieslys te gaan."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Geen TV-invoer gevind nie"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Kan nie die TV-invoer vind nie"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP word nie gesteun nie"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Daar is geen beskikbare invoer om met PIP te wys nie"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Instemmertipe is nie geskik nie. Begin asseblief die Live TV-program vir instemmertipe-TV-invoer."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Kon nie instel nie"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Geen program is gevind om hierdie handeling te behartig nie."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d opnames geskeduleer</item>
       <item quantity="one">%1$d opname geskeduleer</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Kanselleer opname"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Stop opname"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Kyk"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Speel van begin af"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Speel verder"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"As daar te veel programme is wat op dieselfde tyd opgeneem moet word, sal net die programme met die hoër prioriteit opgeneem word."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Stoor"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Eenmalige opnames het die hoogste prioriteit"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Kanselleer"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Kanselleer"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Vergeet"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stop"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Bekyk opnameskedule"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Net hierdie een program"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Neem eerder hierdie een op"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Kanselleer hierdie opname"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Kyk nou"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Vee opnames uit …"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Kan opgeneem word"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Opname geskeduleer"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Opneemkonflik"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Neem tans op"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Kon nie opneem nie"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Lees tans programme om opneemskedules te skep"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Leesprogramme"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Leesprogramme"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Bekyk onlangse opnames"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Die opname van <xliff:g id="PROGRAMNAME">%1$s</xliff:g> is nie volledig nie."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Die opnames van <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> en <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> is onvolledig."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Die opnames van <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> en <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> is onvolledig."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Die opname van <xliff:g id="PROGRAMNAME">%1$s</xliff:g> het nie klaargemaak nie weens onvoldoende bergingspasie."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Die opnames van <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> en <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> het nie klaargemaak nie weens onvoldoende bergingspasie."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Die opnames van <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> en <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> het nie klaargemaak nie weens onvoldoende bergingspasie."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR het meer berging nodig"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Jy sal programme met DVR kan opneem. DVR werk egter nie op die oomblik nie omdat daar nie genoeg berging op jou toestel beskikbaar is nie. Koppel asseblief \'n eksterne hardeskryf wat <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB of groter is en volg die stappe om dit as toestelberging te formateer."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Jy sal programme met DVR kan opneem. DVR werk egter nie op die oomblik nie omdat daar nie genoeg berging op jou toestel beskikbaar is nie. Koppel asseblief \'n eksterne hardeskryf wat <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB of groter is en volg die stappe om dit as toestelberging te formateer."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Te min bergingspasie"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Hierdie program sal nie opgeneem word nie omdat daar te min bergingspasie is. Probeer \'n paar bestaande opnames uitvee."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Berging ontbreek"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Van die berging wat DVR gebruik, ontbreek. Koppel asseblief die eksterne skyf wat jy vroeër gebruik het om DVR te heraktiveer. Andersins kan jy kies om die berging te vergeet as dit nie meer beskikbaar is nie."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Vergeet berging?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Al jou opgeneemde inhoud en skedules sal verloor word."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Stop opname?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Die opgeneemde inhoud sal gestoor word."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Die opname van <xliff:g id="PROGRAMNAME">%1$s</xliff:g> sal gestaak word omdat dit met hierdie program bots. Die inhoud wat opgeneem is, sal gestoor word."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Opname is geskeduleer, maar daar is botsings"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Opname het begin, maar daar is konflikte"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> sal opgeneem word."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Dieselfde program is reeds geskeduleer om om <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> opgeneem te word."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Reeds opgeneem"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Hierdie program is reeds opgeneem. Dit is in die DVR-biblioteek beskikbaar."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Reeksopname geskeduleer"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opnames is geskeduleer vir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname is geskeduleer vir <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opnames is geskeduleer vir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> van hulle sal weens oorvleueling nie opgeneem word nie.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname is geskeduleer vir <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Dit sal weens oorvleueling nie opgeneem word nie.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> opnames is geskeduleer vir <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes van hierdie reeks en ander reekse sal weens oorvleueling nie opgeneem word nie.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname is geskeduleer vir <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodes van hierdie reeks en ander reekse sal weens oorvleueling nie opgeneem word nie.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opnames is geskeduleer vir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episode van \'n ander reeks sal weens oorvleueling nie opgeneem word nie.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname is geskeduleer vir <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 episode van \'n ander reeks sal weens oorvleueling nie opgeneem word nie.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> opnames is geskeduleer vir <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes van \'n ander reeks sal weens oorvleueling nie opgeneem word nie.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname is geskeduleer vir <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodes van \'n ander reeks sal weens oorvleueling nie opgeneem word nie.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Kon nie opgeneemde program vind nie."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Verwante opnames"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Geen programbeskrywing nie)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d opnames</item>
       <item quantity="one">%1$d opname</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Stop om reeks op te neem?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Opgeneemde episodes sal in die DVR-biblioteek beskikbaar bly."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stop"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Geen episodes is tans op die lug nie."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Geen episodes is beskikbaar nie.\nHulle sal opgeneem word sodra hulle beskikbaar is."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minute)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Vandag <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Môre <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Telling"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Opgeneemde programme"</string>
 </resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index bd63879..5b18121 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"ሞኖ"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ስቲሪዮ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"የማጫወቻ መቆጣጠሪያዎች"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"የቅርብ ጊዜ ሰርጦች"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ሰርጦች"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"የቴሌቪዥን አማራጮች"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"የፒአይፒ አማራጮች"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ለዚህ ሰርጥ የማጫወቻ መቆጣጠሪያዎች አይገኝም"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"አጫውት ወይም ለአፍታ አቁም"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"በፍጥነት አሳልፍ"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"የተዘጉ የስዕል መግለጫዎች"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"የማሳያ ሁኔታ"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"ፒአይፒ"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"በርቷል"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"ጠፍቷል"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"ባለብዙ ተሰሚ"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"ተጨማሪ ሰርጦችን ያግኙ"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"ቅንብሮች"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"ምንጭ"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"ማገላበጥ"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"በርቷል"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"ጠፍቷል"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ድምፅ"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"ዋና"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"የፒአይፒ መስኮት"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"አቀማመጥ"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"ከታች በስተቀኝ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ከላይ በስተቀኝ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ከላይ በስተግራ"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"ከታች በስተግራ"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"ጎን ለጎን"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"መጠን"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"ትልቅ"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"ትንሽ"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"የግብዓት ምንጭ"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ቴሌቪዥን (አንቴና/ገመድ)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"ምንም የፕሮግራም መረጃ የለም"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"ምንም መረጃ የለም"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"የታገደ ሰርጥ"</string>
-    <string name="default_language" msgid="4122326459624337928">"ያልታወቀ ቋንቋ"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"ያልታወቀ ቋንቋ"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"ዝግ መግለጫ ጽሑፎች %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"የተዘጉ መግለጫ ጽሑፎች"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"ጠፍቷል"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ቅርጸትን አብጅ"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"ኤስዲ"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"ሰብስብ በ"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"ይህ ፕሮግራም ታግዷል"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"ይህ ፕሮግራም ደረጃ ያልተሰጠው ነው"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"ይህ ፕሮግራም <xliff:g id="RATING">%1$s</xliff:g> ደረጃ ነው የተሰጠው"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ግብዓቱ ራስ-ቃኝን አይደግፍም።"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"ለ«<xliff:g id="TV_INPUT">%s</xliff:g>» ራስ-ቃኝን መጀመር አልተቻለም"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d ሰርጦች ታክለዋል</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"ምንም ሰርጦች አልታከሉም"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ማስተካከያ"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"የወላጅ ቁጥጥሮች"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"በርቷል"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"ጠፍቷል"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"ሌሎች አገሮች"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"ምንም"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ምንም"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"ደረጃ አልተሰጠውም"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"ደረጃ ያልተሰጣቸው ፕሮግራሞችን አግድ"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"ምንም"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"ከፍተኛ ገደቦች"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"መካከለኛ ገደቦች"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"ይህን ሰርጥ ለመመልከት የእርስዎን ፒን ያስገቡ"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"ይህን ፕሮግራም ለመመልከት የእርስዎን ፒን ያስገቡ"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"ይህ ፕሮግራም የ<xliff:g id="RATING">%1$s</xliff:g> ደረጃ ተሰጥቶታል። ይህን ፕሮግራም ለመመልከት የእርስዎን ፒን ያስገቡ።"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"ይህ ፕሮግራም ደረጃ ያልተሰጠው ነው። ይህን ፕሮግራም ለመከታተል የእርስዎን ፒን ያስገቡት።"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"የእርስዎን ፒን ያስገቡ"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"የወላጅ መቆጣጠሪያዎችን ለማዋቀር ፒን ይፍጠሩ።"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"አዲስ ፒን ያስገቡ"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"ይህ ፒን የተሳሳተ ነበር። እንደገና ይሞክሩ።"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"እንደገና ይሞክሩ፣ ፒኑ አይዛመድም"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"ዚፕ ኮድዎን ያስገቡ።"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"የLive TV መተግበሪያ ለቴሌቪዥን ሰርጦቹ ሙሉ የፕሮግራም ዝርዝር ለማቅረብ ዚፕ ኮዱን ይጠቀማል።"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"ዚፕ ኮድዎን ያስገቡ"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"ልክ ያልኾነ ዚፕ ኮድ"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"ቅንብሮች"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"የሰርጥ ዝርዝር አብጅ"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"ለፕሮግራሙ መመሪያዎ ሰርጦችን ይምረጡ"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"የሰርጥ ምንጮች"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"አዲስ ሰርጦች ይገኛሉ"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"የወላጅ መቆጣጠሪያዎች"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"የጊዜ ሽግሽግ"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"የቀጥታ ስርጭቶችን ባሉበት ለማቆም ወይም ለማጠንጠን እየተመለከቱ ሳለ ይቅረጹ።\nማስጠንቀቂያ፦ ይሄ ባለው ከፍተኛ የማከማቻ ፍጆታ ምክንያት የውስጣዊ ማከማቻ ዕድሜውን ሊቀንስ ይችላል።"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"የክፍት ምንጭ ፍቃዶች"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"የክፍት ምንጭ ፍቃዶች"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ግብረ ምላሽ ይላኩ"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"ስሪት"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"ይህን ሰርጥ ለመመልከት ቀኝን ይጫኑ እና የእርስዎን ፒን ያስገቡ"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"ይህን ፕሮግራም ለመመልከት ቀኝን ይጫኑ እና የእርስዎን ፒን ያስገቡ"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"ይህ ፕሮግራም ደረጃ ያልተሰጠው ነው።\nይህን ፕሮግራም ለመመልከት ቀኝን ይጫኑና የእርስዎን ፒን ያስገቡት"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"ይህ ፕሮግራም <xliff:g id="RATING">%1$s</xliff:g> ደረጃ ነው የተሰጠው።\nይህን ፕሮግራም ለመመልከት ቀኝን ይጫኑ እና የእርስዎን ፒን ያስገቡ።"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ይህን ሰርጥ ለመመልከት ነባሪውን የቀጥተኛ ቴሌቪዥን መተግበሪያ ይጠቀሙ።"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"ይህን ፕሮግራም ለመመልከት ነባሪውን የቀጥተኛ ቴሌቪዥን መተግበሪያ ይጠቀሙ።"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"ይህ ፕሮግራም ደረጃ ያልተሰጠው ነው።\nይህን ፕሮግራም ለመመልከት ነባሪውን የቀጥታ ቴሌቪዥን መተግበሪያ ይጠቀሙ።"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"ይህ ፕሮግራም የ<xliff:g id="RATING">%1$s</xliff:g> ደረጃ ነው የተሰጠው።\nይህን ፕሮግራም ለመመልከት ነባሪውን የቀጥተኛ ቴሌቪዥን መተግበሪያ ይጠቀሙ።"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"ፕሮግራም ታግዷል"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"ይህ ፕሮግራም ደረጃ ያልተሰጠው ነው"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"ይህ ፕሮግራም <xliff:g id="RATING">%1$s</xliff:g> ደረጃ ነው የተሰጠው"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ኦዲዮ ብቻ"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"ደካማ ምልክት"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"የቴሌቪዥን ምናሌውን ለመድረስ "<b>"ምረጥን ይጫኑ"</b>"።"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"ምንም የቴሌቪዥን ግብዓት አልተገኘም"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"የቴሌቪዥን ግብዓቱን ማግኘት አልተቻለም"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"ፒአይፒ አይደገፍም"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"ከፒአይፒው ጋር አብሮ ሊታይ የሚችል ግቤት አይገኝም"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"የቃኚ አይነት ተገቢ አይደለም። እባክዎ የቃኚ አይነት ቴሌቪዥን ግብዓት ለማግኘት የቀጥተኛ ሰርጦች መተግበሪያውን ያስጀምሩት።"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"መቃኘት አልተሳካም"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ይህን እርምጃ የሚያከናውን ምንም መተግበሪያ አልተገኘም።"</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d ቀረጻዎች በመርሐግብር ተይዘዋል</item>
       <item quantity="other">%1$d ቀረጻዎች በመርሐግብር ተይዘዋል</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"መቅረጹን አስቀር"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"መቅረጽ አቁም"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ይመልከቱ"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"ከመጀመሪያው አጫውት"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"ከቆመበት ቀጥል"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"በተመሳሳዩ ጊዜ ላይ የሚቀረጹ በጣም ብዙ ፕሮግራሞች ሲኖሩ ከፍ ያለ ቅድሚያ ያላቸው ብቻ ናቸው የሚቀረጹት።"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"አስቀምጥ"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"የአንድ-ጊዜ ቀረጻዎች ከፍተኛ ቅድሚያ ተሰጭነት አላቸው"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"ይቅር"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"ተወው"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"እርሳ"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"አቁም"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"የምዝገባ መርሐግብርን ይመልከቱ"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"ይህ ነጠላ ፕሮግራም"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"በምትኩ ይሄኛውን ቅረጽ"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ይህን ቀረጻ ተወው"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"አሁን ይመልከቱ"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ቀረጻዎችን ሰርዝ…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"ሊቀረጽ የሚችል"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ቀረጻ መርሐግብር ተይዞለታል"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"የቀረጻ ግጭት"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"መቅዳት"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"መቅረጽ አልተሳካም"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"የቀረጻ መርሐግብሮችን ለመፍጠር ፕሮግራሞችን በማንበብ ላይ"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"ፕሮግራሞችን በማንበብ ላይ"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"ፕሮግራሞችን በማንበብ ላይ"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"የቅርብ ጊዜ ቅጂዎችን አሳይ"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"የ<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ቅጂ አልተጠናቀቀም።"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"የ<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> እና <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ቅጂዎች አልተጠናቀቁም።"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"የ<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>፣ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> እና <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ቅጂዎች አልተጠናቀቁም።"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"የ<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ቅጂ ባለው በቂ ያልሆነ ማከማቻ ምክንያት አልተጠናቀቀም።"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"የ<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> እና <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ቅጂዎች ባለው በቂ ያልሆነ ማከማቻ ምክንያት አልተጠናቀቁም።"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"የ<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>፣ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> እና <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ቅጂዎች ባለው በቂ ያልሆነ ማከማቻ ምክንያት አልተጠናቀቁም።"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"ዲቪአር ተጨማሪ ማከማቻ ያስፈልገዋል"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ፕሮግራሞችን በዲቪአር መቅረጽ ይችላሉ። ይሁንና አሁን ዲቪአር እንዲሰራ በመሣሪያዎ ላይ በቂ የማከማቻ ቦታ የለም። እባክዎ <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> ጊባ ወይም ከዚያ በላይ የሆነ ውጫዊ አንጻፊ ይሰኩና እንደ የመሣሪያ ማከማቻ ቅርጸት ለመስራት ያሉትን ደረጃዎች ይከተሉ።"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ፕሮግራሞችን በዲቪአር መቅረጽ ይችላሉ። ይሁንና አሁን ዲቪአር እንዲሰራ በመሣሪያዎ ላይ በቂ የማከማቻ ቦታ የለም። እባክዎ <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> ጊባ ወይም ከዚያ በላይ የሆነ ውጫዊ አንጻፊ ይሰኩና እንደ የመሣሪያ ማከማቻ ቅርጸት ለመስራት ያሉትን ደረጃዎች ይከተሉ።"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"በቂ ማከማቻ የለም"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"በቂ ማከማቻ ስለሌለ ይህ ፕሮግራም አይቀረጽም። አሁን ያሉ አንዳንድ ቀረጻዎችን ለመሰረዝ ይሞክሩ።"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"የሚጎድል ማከማቻ"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"በDVR ጥቅም ላይ የዋለ አንዳንድ ማከማቻ ይጎድላል። DVRን ዳግም ለማንቃት ከዚህ በፊት የሚጠቀሙበትን ውጫዊ አንጻፊ እባክዎ ያገናኙ። በአማራጭነት፣ ከእንግዲህ የማይገኝ ከሆነ ማከማቻውን ለመርሳት መምረጥ ይችላሉ።"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"ማከማቻ ይረሳ?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"ሁሉም የእርስዎ የተቀዳ ይዘት እና መርሐግብሮች ይጠፋሉ።"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"መቅረጽ ይቁም?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"የተቀረጸው ይዘት ይቀመጣል።"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"የ<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ቀረጻ ከዚህ ፕሮግራም ጋር ስለሚጋጭ ይቆማል። የተቀረጸው ይዘት ይቀመጣል።"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ምዝገባ መርሐግብር ተይዞለታል፣ ነገር ግን ግጭቶች አሉ"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ቀረጻ ተጀምሯል፣ ነገር ግን ግጭቶች አሉት"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ይቀረጻል።"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"ተመሳሳዩ ፕሮግራም አስቀድሞ በ<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> ላይ እንዲቀረጽ መርሐግብር ተይዞለታል።"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"አስቀድሞ ተቀርጿል"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"ይህ ፕሮግራም አስቀድሞ ተቀርጿል። በዲቪአር ቤተ-መጽሐፍት ውስጥ ይገኛል።"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"የተከታታዮች ቀረጻ መርሐግብር ተይዞለታል"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_3">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል።</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_3">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል።</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_3">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል። ከእነሱ ውስጥ <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> በግጭቶች ምክንያት አይቀረጹም።</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_3">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል። ከእነሱ ውስጥ <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> በግጭቶች ምክንያት አይቀረጹም።</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_4">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል። <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> የዚህ ተከታታይ እና የሌሎች ተከታታዮች ትርዒት ክፍሎች በግጭቶች ምክንያት አይቀረጹም።</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_4">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል። <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> የዚህ ተከታታይ እና የሌሎች ተከታታዮች ትርዒት ክፍሎች በግጭቶች ምክንያት አይቀረጹም።</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_3">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል። 1 የሌሎች ተከታታዮች የትርዒት ክፍል በግጭት ምክንያት አይቀረጽም።</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_3">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል። 1 የሌሎች ተከታታዮች የትርዒት ክፍል በግጭት ምክንያት አይቀረጽም።</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_4">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል። <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> የሌላ ተከታታይ የትዕይንት ክፍሎች በግጭቶች ምክንያት አይቀረጹም።</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ቀረጻዎች ለ<xliff:g id="SERIESNAME_4">%2$s</xliff:g> የጊዜ መርሐግብር ተይዞላቸዋል። <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> የሌላ ተከታታይ የትዕይንት ክፍሎች በግጭቶች ምክንያት አይቀረጹም።</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"የተቀረጸ ፕሮግራም አልተገኘም።"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"ተዛማጅ ቀረጻዎች"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(ምንም የፕሮግራም መግለጫ የለም)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d ቀረጻዎች</item>
       <item quantity="other">%1$d ቀረጻዎች</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"የተከታታይ ቀረጻ ይቆም?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"የተቀረጹ ክፍሎች በዲቪአር ቤተ-መጽሐፍቱ ላይ የሚገኙ እንደሆኑ ይቆያሉ።"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"አቁም"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ምንም ተከታታይ የትዕይንት ክፍሎች የሉም።"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"ምንም ክፍሎች አይገኙም።\nልክ የሚገኙ ሲሆኑ ይቀረጻሉ።"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d ደቂቃዎች)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ዛሬ"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ነገ"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"ነጥብ"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"የተቀረጹ ፕሮግራሞች"</string>
 </resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index f91139b..a1b4720 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"أحادية"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ستيريو"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"عناصر التحكم في التشغيل"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"أحدث القنوات"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"القنوات"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"خيارات التلفزيون"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"‏خيارات PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"عناصر تحكم التشغيل غير متاحة لهذه القناة"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"تشغيل الفيديو أو إيقافه مؤقتًا"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"تقديم سريع"</string>
@@ -32,40 +31,22 @@
     <string name="channels_item_program_guide" msgid="2889807207930678418">"دليل البرامج"</string>
     <string name="channels_item_setup" msgid="6557412175737379022">"تتوفر قنوات جديدة"</string>
     <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"فتح <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
-    <string name="options_item_closed_caption" msgid="5945274655046367170">"التسميات التوضيحية المغلقة"</string>
+    <string name="options_item_closed_caption" msgid="5945274655046367170">"الترجمة والشرح"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"وضع العرض"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"تشغيل"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"إيقاف"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"إعدادات صوتية متعددة"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"جلب قنوات أخرى"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"الإعدادات"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"المصدر"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"تبديل"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"تشغيل"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"إيقاف"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"الصوت"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"الرئيسي"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"‏نافذة PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"التنسيق"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"أسفل اليمين"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"أعلى اليمين"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"أعلى اليسار"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"أسفل اليسار"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"جنبًا إلى جنب"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"الحجم"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"كبيرة"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"صغيرة"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"مصدر الإدخال"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"تلفزيون (هوائي/كابل)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"لا تتوفّر معلومات عن البرنامج"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"لا توجد معلومات"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"القناة المحظورة"</string>
-    <string name="default_language" msgid="4122326459624337928">"لغة غير معروفة"</string>
-    <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"التسميات التوضيحية المغلقة"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"لغة غير معروفة"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"‏مقاطع ترجمة وشرح %1$d"</string>
+    <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"الترجمة والشرح"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"إيقاف"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"تخصيص التنسيق"</string>
-    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"تعيين التفضيلات عبر النظام للتسميات التوضيحية المغلقة"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"تعيين التفضيلات عبر النظام للترجمة والشرح"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"وضع العرض"</string>
     <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"إعدادات صوتية متعددة"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"أحادية"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"دقة قياسية"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"تجميع بحسب"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"تم حظر هذا البرنامج"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"لم يتم تقييم هذا البرنامج"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"تم تصنيف هذا البرنامج على أنه <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"الإدخال ليس متوافقًا مع الفحص التلقائي"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"تعذر بدء البحث التلقائي في \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -96,7 +78,6 @@
       <item quantity="one">‏تمت إضافة %1$d قناة</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"لم تتم إضافة قنوات"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"موالف"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"عناصر التحكم الأبوي"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"تشغيل"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"إيقاف"</string>
@@ -112,6 +93,8 @@
     <string name="other_countries" msgid="8342216398676184749">"بلدان أخرى"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"لا شيء"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"لا شيء"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"غير مقيَّم"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"حظر البرامج غير المقيَّمة"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"لا شيء"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"قيود مرتفعة"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"قيود متوسّطة"</string>
@@ -128,6 +111,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"أدخل رقم التعريف الشخصي لمشاهدة هذه القناة"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"أدخل رقم التعريف الشخصي لمشاهدة هذا البرنامج"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"هذا البرنامج يحمل التقييم <xliff:g id="RATING">%1$s</xliff:g>. يمكنك إدخال رقم التعريف الشخصي لمشاهدة هذا البرنامج"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"لم يتم تقييم هذا البرنامج. أدخل رقم التعريف الشخصي لمشاهدة هذا البرنامج"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"أدخل رقم التعريف الشخصي"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"لتعيين عناصر التحكم الأبوي، عليك إنشاء رقم تعريف شخصي"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"إدخال رقم تعريف شخصي جديد"</string>
@@ -143,22 +127,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"رقم التعريف الشخصي هذا خاطئ. أعد المحاولة."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"أعد المحاولة، رقم التعريف الشخصي غير مطابق"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"أدخل الرمز البريدي."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"‏سيستخدم تطبيق Live TV الرمز البريدي لتوفير دليل برامج كامل لقنوات التلفزيون."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"أدخل الرمز البريدي"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"الرمز البريدي غير صالح"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"الإعدادات"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"تخصيص قائمة قنوات"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"اختر القنوات الخاصة بدليل البرامج."</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"مصادر القنوات"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"تتوفر قنوات جديدة."</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"أدوات الرقابة الأبوية"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"الانتقال الزمني"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"يمكنك التسجيل أثناء المشاهدة حتى يتسنى لك إيقاف بث البرامج المباشرة مؤقتًا أو إرجاع البث إلى أوقات سابقة.\nتحذير: قد يؤدي هذا إلى استهلاك مكثّف لمساحة وحدة التخزين الداخلية؛ ما يؤدي إلى نفادها في فترة قصيرة."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"تراخيص البرامج المفتوحة المصدر"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"تراخيص البرامج المفتوحة المصدر"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"إرسال تعليقات"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"الإصدار"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"لمشاهدة هذه القناة، اضغط على اليمين وأدخل رقم التعريف الشخصي"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"لمشاهدة هذا البرنامج، اضغط على اليمين وأدخل رقم التعريف الشخصي"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"لم يتم تقييم هذا البرنامج.\nلمشاهدة هذا البرنامج، اضغط على اليمين وأدخل رقم التعريف الشخصي"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"تم تصنيف هذا البرنامج على أنه <xliff:g id="RATING">%1$s</xliff:g>.\nلمشاهدة هذا البرنامج، اضغط على اليمين وأدخل رقم التعريف الشخصي."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"‏لمشاهدة هذه القناة، يمكنك استخدام تطبيق Live TV الافتراضي."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"‏لمشاهدة هذا البرنامج، يمكنك استخدام تطبيق Live TV الافتراضي."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"‏لم يتم تقييم هذا البرنامج.\nلمشاهدة هذا البرنامج، استخدم تطبيق Live TV الافتراضي."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"‏هذا البرنامج يحمل التقييم <xliff:g id="RATING">%1$s</xliff:g>.\nلمشاهدة هذا البرنامج، يمكنك استخدام تطبيق Live TV الافتراضي."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"البرنامج محظور"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"لم يتم تقييم هذا البرنامج"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"تم تصنيف هذا البرنامج على أنه <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"الصوت فقط"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"الإشارة ضعيفة"</string>
@@ -197,10 +190,8 @@
     <string name="intro_description" msgid="7806473686446937307">"‏"<b>"اضغط على \"تحديد\""</b>" للوصول إلى قائمة TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"لم يتم العثور على إدخال تلفزيون"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"لا يمكن العثور على إدخال تلفزيون"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"‏خدمة PIP ليست متوافقة"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"‏ليس هناك إدخال متاح يمكن عرضه باستخدام PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"نوع الموالف غير مناسب، لذلك يُرجى تشغيل تطبيق القنوات المباشرة لنوع الموالف إدخال التلفزيون."</string>
-    <string name="msg_tune_failed" msgid="3277419551849972252">"أخفق التوليف"</string>
+    <string name="msg_tune_failed" msgid="3277419551849972252">"تعذّر التوليف"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"لم يتم العثور على تطبيق يمكنه مباشرة هذا الإجراء."</string>
     <string name="msg_all_channels_hidden" msgid="777397634062471936">"كل قنوات المصدر مخفية.\nحدد على الأقل قناة واحدة لمشاهدتها."</string>
     <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"الفيديو غير متوفر بشكل مفاجئ"</string>
@@ -262,6 +253,8 @@
       <item quantity="other">‏%1$d تسجيل حسب جدول زمني</item>
       <item quantity="one">‏%1$d تسجيل حسب جدول زمني</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"إلغاء التسجيل"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"إيقاف التسجيل"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"مشاهدة"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"تشغيل من البداية"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"استئناف التشغيل"</string>
@@ -298,9 +291,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"عندما تكون هناك برامج كثيرة جدًا مطلوب تسجيلها في آنٍ واحد، فلن يتم تسجيل أي برامج منها إلا تلك ذات القدر الأعلى من الأولوية فقط."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"حفظ"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"تسجيلات المرة الواحدة لها الأولوية القصوى"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"إلغاء"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"إلغاء"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"حذف"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"إيقاف"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"عرض جدول عمليات التسجيل الزمني"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"هذا البرنامج وحده"</string>
@@ -310,25 +300,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"تسجيل هذا بدلاً من ذلك"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"إلغاء هذا التسجيل"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"المشاهدة الآن"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"حذف التسجيلات…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"قابل للتسجيل"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"تمتّ جدولة التسجيل"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"تعارض في التسجيل"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"جارٍ التسجيل"</string>
-    <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"أخفق التسجيل"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"جارٍ قراءة البرامج لإنشاء جداول زمنية للتسجيل"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"جارٍ قراءة البرامج"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"تعذّر التسجيل"</string>
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"جارٍ قراءة البرامج"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"عرض التسجيلات الأخيرة"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"لم يكتمل تسجيل <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"لم يكتمل تسجيل كل من <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> و<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"لم يكتمل تسجيل كل من <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> و<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> و<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"لم يكتمل تسجيل <xliff:g id="PROGRAMNAME">%1$s</xliff:g> نظرًا لأن سعة التخزين غير كافية."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"لم يكتمل تسجيل كل من <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> و<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> نظرًا لأن سعة التخزين غير كافية."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"لم يكتمل تسجيل كل من <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> و<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> و<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> نظرًا لأن سعة التخزين غير كافية."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"يحتاج مسجِّل الفيديو الرقمي إلى المزيد من السعة التخزينية"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ستتمكن من تسجيل البرامج باستخدام مسجّل الفيديو الرقمي؛ ولكن ليست هناك سعة تخزينية كافية على جهازك الآن ليعمل مسجِّل الفيديو الرقمي. يُرجى توصيل محرك أقراص خارجي بسعة تخزين <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>غيغابايت أو أكبر واتباع الخطوات لتهيئته كوحدة تخزين للجهاز."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ستتمكن من تسجيل البرامج باستخدام مسجّل الفيديو الرقمي؛ ولكن ليست هناك سعة تخزينية كافية على جهازك الآن ليعمل مسجِّل الفيديو الرقمي. يُرجى توصيل محرك أقراص خارجي بسعة تخزين <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>غيغابايت أو أكبر واتباع الخطوات لتهيئته كوحدة تخزين للجهاز."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"السعة التخزينية غير كافية"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"لن يتم تسجيل هذا البرنامج لأنه ليست هناك سعة تخزين كافية. جرِّب حذف بعض التسجيلات الحالية."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"سعة التخزين المفقودة"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"‏بعض سعة التخزين المستخدمة في جهاز DVR مفقود. يُرجى توصيل محرك الأقراص الخارجي الذي سبق لك استخدامه لإعادة تمكين جهاز DVR. بدلاً من ذلك، يمكنك اختيار حذف سعة التخزين إذا لم تعد متاحة."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"هل تريد حذف سعة التخزين؟"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"سيتم فقد جميع المحتويات والجداول الزمنية المسجَّلة."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"هل تريد إيقاف التسجيل؟"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"سيتم حفظ المحتوى الذي تم تسجيله."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"سيتم إيقاف تسجيل <xliff:g id="PROGRAMNAME">%1$s</xliff:g> لأنه يتعارض مع هذا البرنامج. وسيتم حفظ المحتوى الذي تم تسجيله."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"تمت إضافة جدول زمني لإجراء التسجيل ولكنه يتعارض مع جداول زمنية أخرى"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"تم بدء التسجيل ولكنه يتعارض مع جداول زمنية أخرى"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"لن يتم تسجيل <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -350,17 +343,49 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"تم إعداد جدول زمني من قبل لتسجيل البرنامج نفسه في <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"تم التسجيل من قبل"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"‏تم تسجيل هذا البرنامج من قبل. وسيكون متاحًا في مكتبة DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"تمت جدولة تسجيل المسلسل"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="zero">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="two">تمت جدولة تسجيلين (<xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="few">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيلات لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="many">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيلاً لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">تمت جدولة تسجيل واحد (<xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="zero">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> من الحلقات بسبب تعارض المواعيد.</item>
+      <item quantity="two">تمت جدولة تسجيلين (<xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> من الحلقات بسبب تعارض المواعيد.</item>
+      <item quantity="few">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيلات لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> من الحلقات بسبب تعارض المواعيد.</item>
+      <item quantity="many">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيلاً لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> من الحلقات بسبب تعارض المواعيد.</item>
+      <item quantity="other">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> من الحلقات بسبب تعارض المواعيد.</item>
+      <item quantity="one">تمت جدولة تسجيل واحد (<xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. ولن يتم إجراء هذا التسجيل بسبب تعارض المواعيد.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="zero">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات هذا المسلسل والمسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="two">تمت جدولة تسجيلين (<xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات هذا المسلسل والمسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="few">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> تسجيلات لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات هذا المسلسل والمسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="many">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> تسجيلاً لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات هذا المسلسل والمسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="other">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات هذا المسلسل والمسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="one">تمت جدولة تسجيل واحد (<xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> من حلقات هذا المسلسل والمسلسل الآخر بسبب تعارض المواعيد.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="zero">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل حلقة واحدة من المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="two">تمت جدولة تسجيلين (<xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل حلقة واحدة من المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="few">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيلات لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل حلقة واحدة من المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="many">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيلاً لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل حلقة واحدة من المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="other">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. ولن يتم تسجيل حلقة واحدة من المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="one">تمت جدولة تسجيل واحد (<xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. ولن يتم تسجيل حلقة واحدة من المسلسل الآخر بسبب تعارض المواعيد.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="zero">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="two">تمت جدولة تسجيلين (<xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="few">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> تسجيلات لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="many">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> تسجيلاً لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="other">تمت جدولة <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> تسجيل لمسلسل <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> من حلقات المسلسل الآخر بسبب تعارض المواعيد.</item>
+      <item quantity="one">تمت جدولة تسجيل واحد (<xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>) لمسلسل <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. ولن يتم تسجيل <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> من حلقات المسلسل الآخر بسبب تعارض المواعيد.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"لم يتم العثور على البرنامج المُسّجل"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"تسجيلات ذات صلة"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(لا يتوفر وصف للبرنامج)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="zero">‏%1$d تسجيل</item>
       <item quantity="two">‏تسجيلان (%1$d)</item>
@@ -388,6 +413,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"هل تريد إيقاف تسجيل السلسلة؟"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"‏ستظل الحلقات المسجّلة متاحة في مكتبة DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"إيقاف"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ليست هناك حلقات يتم بثها على الهواء حاليًا."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"لا تتوفر أي حلقات.\nسيتم تسجيلها بعد توفرها."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="zero">‏(%1$d دقيقة)</item>
@@ -403,4 +429,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> اليوم"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> غدًا"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"النتيجة"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"البرامج المسجّلة"</string>
 </resources>
diff --git a/res/values-az/arrays.xml b/res/values-az-rAZ/arrays.xml
similarity index 100%
rename from res/values-az/arrays.xml
rename to res/values-az-rAZ/arrays.xml
diff --git a/res/values-az/rating_system_strings.xml b/res/values-az-rAZ/rating_system_strings.xml
similarity index 100%
rename from res/values-az/rating_system_strings.xml
rename to res/values-az-rAZ/rating_system_strings.xml
diff --git a/res/values-az/strings.xml b/res/values-az-rAZ/strings.xml
similarity index 78%
rename from res/values-az/strings.xml
rename to res/values-az-rAZ/strings.xml
index 6ccb6d2..7fe8ae8 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az-rAZ/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Oyun kontrolu"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Son kanallar"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanallar"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV seçənəkləri"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP seçənəklər"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Oxutma idarə elementləri bu kanal üçün əlçatan deyil"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Oxudun və ya durdurun"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Sürətlə irəli"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Qapalı başlıqlar"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Ekran rejimi"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Aktiv"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Qeyri-aktiv"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Daha çox kanal əldə edin"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Ayarlar"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Mənbə"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Dəyişdirin"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Aktiv"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Qeyri-aktiv"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Səs"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Əsas"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP pəncərəsi"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Etiket"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Aşağı sağ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Yuxarı sağ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Yuxarı sol"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Aşağı sol"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Yan-yana"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Ölçü"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Böyük"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Kiçik"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Mənbəni daxil edin"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"No proqram informasiya"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Məlumat yoxdur"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"bloklanmış kanallar"</string>
-    <string name="default_language" msgid="4122326459624337928">"Naməlum dil"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Naməlum dil"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtitr %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Qapalı başlıqlar"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Deaktiv"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Formatı fərdiləşdirin"</string>
@@ -85,6 +66,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Qruplaşdırın"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Bu proqram bloklanıb."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Bu proqram reytinqsizdir"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Bu proqram <xliff:g id="RATING">%1$s</xliff:g> ilə qiymətləndirilib."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Daxiletmə avto-skanı dəstəkləmir"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' üçün avto-skanı başlatmaq olmur"</string>
@@ -94,7 +76,6 @@
       <item quantity="one">%1$d kanal əlavə edildi</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Kanal əlavə edilmədi"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Valideyn nəzarəti"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Aktiv"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Deaktiv"</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Digər ölkələr"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Heç bir"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Heç bir"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Reytinqsiz"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Reytinqsiz proqramları blok edin"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Heç bir"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Yüksək məhdudiyyətlər"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Orta məhdudiyyətlər"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Bu kanalı izləmək üçün PİN kodunuzu daxil edin"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Bu proqramı izləmək üçün PİN kodunuzu daxil edin"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Bu proqram <xliff:g id="RATING">%1$s</xliff:g> ilə qiymətləndirilib. Bu proqramı izləmək üçün PİN kodunuzu daxil edin"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Bu proqram reytinqsizdir. Bu proqramı izləmək üçün PIN\'i daxil edin"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PİN kodunuzu daxil edin"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Valideyn nəzarəi yaratmaq üçün PİN yaradın"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Yeni PIN kodu daxil edin"</string>
@@ -137,22 +121,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Həmin PİN kod səhv idi. Yenidən cəhd edin."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Yenidən cəhd edin, PİN uyğun deyil"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Poçt İndeksi daxil edin."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Canlı Kanal tətbiqi TV kanallarını tam proqram təlimatı ilə təmin etmək üçün Poçt İndeksi istifadə edəcək."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Poçt İndeksi daxil edin"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Yanlış Poçt İndeksi"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Ayarlar"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Kanal siyahısını fərdiləşdirin"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Proqram təlimatınız üçün kanal seçin"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanal mənbələri"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Yeni əlçatan kanallar"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Valideyn nəzarəti"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Zaman keçidi"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"İzləyərkən qeyd edin, beləliklə canlı proqramlara fasilə verə və ya geri sara bilərsiniz.\nXəbərdarlıq: İnstensiv yaddaş istifadəsi daxili yaddaşı azalda bilər."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Açıq mənbə lisenziyaları"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Açıq mənbə lisenziyaları"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Cavab rəyi göndərin"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versiya"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Bu kanalı izləmək üçün Sağa basın və PİN kodunuzu daxil edin"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Bu proqramı izləmək üçün Sağa basın və PİN kodunuzu daxil edin"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Bu proqram reytinqsizdir.\nBu proqramı izləmək üçün Right düyməsini basın və PIN kodu daxil edin"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Bu proqram <xliff:g id="RATING">%1$s</xliff:g> ilə qiymətləndirilib.\nBu proqramı izləmək üçün Sağa basın və PİN kodunuzu daxil edin."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Bu kanalı izləmək üçün  defolt Live TV tətbiqini istifadə edin."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Bu proqramı izləmək üçün defolt Live TV tətbiqini istifadə edin."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Bu proqram reytinqsizdir.\nBu proqramı izləmək üçün defolt Live TV tətbiqindən istifadə edin."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Bu proqram <xliff:g id="RATING">%1$s</xliff:g> ilə qiymətləndirilib. \n Bu proqramı izləmək üçün defolt Live TV tətbiqini istifadə edin."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Proqram blok edilib"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Bu proqram reytinqsizdir"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Bu proqram <xliff:g id="RATING">%1$s</xliff:g> ilə qiymətləndirilib."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Yalnız Audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Zəif siqnal"</string>
@@ -183,8 +176,6 @@
     <string name="intro_description" msgid="7806473686446937307">"TV menyusuna giriş üçün "<b>"SEÇİN basın"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"TV daxiletmə tapılmadı"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV daxiletmə tapılmır"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP dəstəklənmir"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP ilə göstərilə biləcək əlçatan daxiletmə yoxdur"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Sazlama növü uyğun deyil. TV daxiletmə sazlama növü üçün Canlı Kanallar tətbiqini işə salın."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Sazlama alınmadı"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Bu əməliyyatı idarə etmək üçün heç bir tətbiq tapılmadı."</string>
@@ -228,6 +219,8 @@
       <item quantity="other">%1$d qeydə alma təyin edildi</item>
       <item quantity="one">%1$d qeydə alma təyin edildi</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Qeyd etməni ləğv edin"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Qeyd etməyi dayandırın"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"İzləyin"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Əvvəldən oxudun"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Oxutmağa davam edin"</string>
@@ -260,9 +253,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Eyni anda qeydə alınacaq bir neçə proqram olduqda, yalnız vacib olanlar qeydə alınacaq."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Yadda saxlayın"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Bir dəfəlik qeydiyyatlar yüksək prioritetlidir"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Ləğv edin"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Ləğv edin"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Unudun"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Dayandırın"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Qeydiyyat cədvəlinə baxın"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Tək bu proqram"</string>
@@ -272,25 +262,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Əvəzinə bunu qeydə alın"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Bu qeydə almanı ləğv edin"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"İndi baxın"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Qeydə almaları silin..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Qeydə alınabilən"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Qeydiyyat planlaşdırılıb"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Qeydiyyat münaqişəsi"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Qeydə alınır"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Qeydə alma uğursuz oldu"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Qeyd etmə cədvəli yaratmaq üçün proqramlar oxunur"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Oxuma proqramları"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Oxuma proqramları"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Son yazılara baxın"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> qeydə alınması tamamlanmadı."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> və <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> qeydə alınması tamamlanmadı."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> və <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> qeydə alınması tamamlanmadı."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Yetərsiz yaddaş səbəbi ilə <xliff:g id="PROGRAMNAME">%1$s</xliff:g> qeydə alınması tamamlanmadı."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Yetərsiz yaddaş səbəbi ilə <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> və <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> qeydə alınması tamamlanmadı."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Yetərsiz yaddaş səbəbi ilə <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> və <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> qeydə alınması tamamlanmadı."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR üçün əlavə yaddaş tələb olunur"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR ilə proqram qeydə ala biləcəksiniz. Hazırda DVR-ın işləməsi üçün cihazda kifayət qədər yaddaş yoxdur. <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB və ya daha böyük həcmli xarici yaddaşı qoşun və cihaz yaddaşı olaraq format etmək üçün mərhələlərə riayət edin."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR ilə proqram qeydə ala biləcəksiniz. Hazırda DVR-ın işləməsi üçün cihazda kifayət qədər yaddaş yoxdur. <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB və ya daha böyük həcmli xarici yaddaşı qoşun və cihaz yaddaşı olaraq format etmək üçün mərhələlərə riayət edin."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Kifayət qədər yer yoxdur"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Kifayət qədər boş yer olmadığı üçün bu proqram qeydə alınmayacaq. Bəzi mövcud qeydə almaları silməyə çalışın."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Yaddaş catışmır"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR tərəfindən istifadə olunan yaddaşın bir hissəsi əlçatan deyil. DVR\'ı yenidən aktiv etməmişdən əvvəl istifadə etdiyiniz xarici diskə qoşulun. Bundan başqa, artıq əlçatan deyilsə, yaddaşı unutmağı seçə bilərsiniz."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Yaddaş ehtiyyatını unutmusunuz?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Qeydə alınmış bütün məzmun və cədvəlləriniz itəcək."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Qeydetmə dayandırılsın?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Qeydə alınan məzmun yadda saxlanacaq."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Bu proqram ilə ziddiyyəti olduğu üçün <xliff:g id="PROGRAMNAME">%1$s</xliff:g> proqramının qeydə alınması dayandırılacaq. Qeydə alınmış məzmun yadda saxlanacaq."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Qeydiyyat vaxtı təyin edilib lakin ziddiyətlər var"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Qeydə alma başladı, lakin ziddiyətlər var."</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> qeydə alınacaq."</string>
@@ -308,17 +301,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Eyni proqramın qeydə alınması üçün artıq <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> radələrində vaxt təyin edilib."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Artıq qeydə alınıb"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Bu proqram artıq qeydə alınıb. O, DVR kitabxanasında əlçatandır."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Seriyaların qeydiyyatı planlaşdırıldı"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_3">%2$s</xliff:g> üçün təyin edildi.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_1">%2$s</xliff:g> üçün təyin edildi.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_3">%2$s</xliff:g> üçün təyin edildi. Onlardan <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ədədi ziddiyyət səbəbilə qəydə alınmayacaq.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_1">%2$s</xliff:g> üçün təyin edildi. Bu, ziddiyyət səbəbilə qəydə alınmayacaq.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_4">%2$s</xliff:g> üçün təyin edildi. Bu seriyaların <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizodu və digər seriyalar ziddiyyət səbəbilə qeydə alınmayacaq.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_1">%2$s</xliff:g> üçün təyin edildi. Bu seriyaların <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> epizodu və digər seriyalar ziddiyyət səbəbilə qeydə alınmayacaq.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_3">%2$s</xliff:g> üçün təyin edildi. Digər seriyaların 1 epizodu ziddiyyət səbəbilə qeydə alınmayacaq.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_1">%2$s</xliff:g> üçün təyin edildi. Digər seriyaların 1 epizodu ziddiyyət səbəbilə qeydə alınmayacaq.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_4">%2$s</xliff:g> üçün təyin edildi. Digər seriyaların <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizodu ziddiyyət səbəbilə qeydə alınmayacaq.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> qeydə alma <xliff:g id="SERIESNAME_1">%2$s</xliff:g> üçün təyin edildi. Digər seriyaların <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> epizodu ziddiyyət səbəbilə qeydə alınmayacaq.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Qeyd edilmiş proqram tapılmadı."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Əlaqədar qeydetmələr"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Proqramın təsviri yoxdur)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d qeyd etmə</item>
       <item quantity="one">%1$d qeyd etmə</item>
@@ -338,6 +343,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Ardıcıl qeydə alma dayandırılsın?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Qeydə alınmış epizodlar DVR kitabxanasında əlçatan olacaq."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Dayandırın"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Heç bir epizod indi canlı yayımda deyil."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Heç bir epizod əlçatan deyil.\nOnlar, əlçatan olduqda qeydə alınacaq."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d dəqiqə)</item>
@@ -349,4 +355,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> bugün"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> sabah"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Hesab"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Qeyd edilmiş Proqramlar"</string>
 </resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index ab202fe..cd4ae37 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"моно"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"стерео"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Контроли за пускане"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Скорошни канали"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Канали"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Опции за TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Опции за PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"За този канал няма налични контроли за възпроизвеждане"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Пускане или поставяне на пауза"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Превъртане напред"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Надписи"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Показв.: Режим"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Вкл."</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Изкл."</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Много записи"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Още канали"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Настройки"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Източник"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Размяна"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Вкл."</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Изкл."</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Звук"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Основен"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Прозорец на PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Оформление"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Долу вдясно"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Горе вдясно"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Горе вляво"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Долу вляво"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Редом"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Размер"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Голям"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Малък"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Вход"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Телевизор (антена/кабел)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Няма информация за програмите"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Няма информация"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Блокиран канал"</string>
-    <string name="default_language" msgid="4122326459624337928">"Неизвестен език"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Неизвестен език"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Надписи: %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Надписи"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Изключване"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Форматиране: Персон."</string>
@@ -79,10 +60,11 @@
     <string name="edit_channels_item_group_by" msgid="7794571851966798199">"Групиране по"</string>
     <string name="edit_channels_group_by_sources" msgid="5481053601210461217">"Източник на канала"</string>
     <string name="edit_channels_group_by_hd_sd" msgid="5582719665718278819">"Висока/стандартна детайлност"</string>
-    <string name="edit_channels_group_divider_for_hd" msgid="5311355566660389423">"Висока детайлност"</string>
+    <string name="edit_channels_group_divider_for_hd" msgid="5311355566660389423">"HD"</string>
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"Стандартна детайлност"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Групиране по"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Тази програма е блокирана"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Тази програма е без класификация"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Класификацията на тази програма е „<xliff:g id="RATING">%1$s</xliff:g>“"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Входът не поддържа автоматично сканиране"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Автоматичното сканиране за „<xliff:g id="TV_INPUT">%s</xliff:g>“ не може да се стартира"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">Добавен е %1$d канал</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Няма добавени канали"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Тунер"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Родителски контрол"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Вкл."</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Изкл."</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Други държави"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Няма"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Няма"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Без класификация"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Програми без класиф.: Блокир."</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Няма"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Високи ограничения"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Средни ограничения"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Въведете ПИН кода си, за да гледате този канал"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Въведете ПИН кода си, за да гледате тази програма"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Тази програма е класифицирана като „<xliff:g id="RATING">%1$s</xliff:g>“. Въведете ПИН кода си, за да я гледате"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Тази програма е без класификация. Въведете ПИН кода си, за да я гледате"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Въведете ПИН кода си"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"За да зададете родителски контроли, създайте ПИН код"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Въведете новия ПИН код"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Този ПИН код бе грешен. Опитайте отново."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Опитайте отново, ПИН кодът не е идентичен"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Въведете пощенския си код."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Приложението Телевизия онлайн ще използва пощенския код, за да предоставя пълния програмен справочник за телевизионните канали."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Въведете пощенския си код"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Пощенският код е невалиден"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Настройки"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Персон. на списъка с канали"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Изберете канали за програмния си справочник"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Източници на канали"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Налице са нови канали"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Родителски контроли"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Отложено възпроизвеждане"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Записвайте, докато гледате, за да можете да поставяте на пауза или превъртате назад програми на живо.\nПредупреждение: Тази функция може да намали живота на вътрешното хранилище чрез интензивното му използване."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Лицензи за отворен код"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Лицензи за отворен код"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Изпращане на отзиви"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Версия"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"За да гледате този канал, натиснете стрелката за надясно и въведете ПИН кода си"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"За да гледате тази програма, натиснете стрелката за надясно и въведете ПИН кода си"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Тази програма е без класификация.\nЗа да я гледате, натиснете бутона за надясно и въведете ПИН кода си."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Класификацията на тази програма е „<xliff:g id="RATING">%1$s</xliff:g>“.\nЗа да я гледате, натиснете стрелката за надясно и въведете ПИН кода си."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"За да гледате този канал, използвайте стандартното приложение за телевизия на живо."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"За да гледате тази програма, използвайте стандартното приложение за телевизия на живо."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Тази програма е без класификация.\nЗа да я гледате, използвайте стандартното приложение за телевизия на живо."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Тази програма е класифицирана като „<xliff:g id="RATING">%1$s</xliff:g>“.\nЗа да я гледате, използвайте стандартното приложение за телевизия на живо."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Програмата е блокирана"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Тази програма е без класификация"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Класификацията на тази програма е „<xliff:g id="RATING">%1$s</xliff:g>“"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Само аудио"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Слаб сигнал"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Натиснете „ИЗБИРАНЕ“"</b>" за достъп до менюто на телевизора."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Няма намерен вход на телевизора"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Входът на телевизора не може да бъде намерен"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Функцията „Картина в картината“ не се поддържа"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Няма наличен вход, който да може да се показва с PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Типът тунер не е подходящ. Моля, стартирайте приложението Live TV за телевизионен вход от типа „тунер“."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Настройването не бе успешно"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Не бе намерено приложение за извършване на това действие."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d насрочени записа</item>
       <item quantity="one">%1$d насрочен запис</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Анулиране на записа"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Спиране на записа"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Гледане"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Пускане от началото"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Продължаване"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Когато има прекалено много програми за записване по едно и също време, ще бъдат записани само тези с най-висок приоритет."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Запазване"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Най-висок приоритет имат еднократните записи"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Отказ"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Отказ"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Забравяне"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Спиране"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Вижте графика за записване"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Само тази програма"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Записване на тази програма"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Анулиране на този запис"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Гледайте сега"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Изтриване на записи…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"С възможност за запис"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Записът е насрочен"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Конфликт със записа"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Записва се"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Записването не бе успешно"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Програмите се четат с цел създаване на графици за записване"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Програмите се четат"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Програмите се четат"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Преглед на скорошните записи"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Записът на „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ е непълен."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Записите на „<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>“ и „<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>“ са непълни."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Записите на „<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>“, „<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>“ и „<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>“ са непълни."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Записването на „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ не завърши поради недостатъчно място в хранилището."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Записването на „<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>“ и „<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>“ не завърши поради недостатъчно място в хранилището."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Записването на „<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>“, „<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>“ и „<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>“ не завърши поради недостатъчно място в хранилището."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Дигиталният видеорекордер се нуждае от още място за съхранение"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Ще сте в състояние да записвате програми посредством дигиталния видеорекордер. В момента обаче той не може да работи, тъй като няма достатъчно място в хранилището на устройството ви. Моля, свържете външен диск с размер от поне <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> ГБ и изпълнете стъпките, за да го форматирате като хранилище на устройството."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Ще сте в състояние да записвате програми посредством дигиталния видеорекордер. В момента обаче той не може да работи, тъй като няма достатъчно място в хранилището на устройството ви. Моля, свържете външен диск с размер от поне <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> ГБ и изпълнете стъпките, за да го форматирате като хранилище на устройството."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Няма достатъчно място в хранилището"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Тази програма няма да бъде записана, защото няма достатъчно място в хранилището. Пробвайте да изтриете някои съществуващи записи."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Хранилището липсва"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Част от използваното от цифровия видеорекордер хранилище липсва. Моля, свържете по-рано ползвания от вас външен диск, за да активирате отново видеорекордера. Друга възможност е да изберете хранилището да се забрави, ако вече не е налично."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Да се забрави ли хранилището?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Цялото ви записано съдържание и графици ще бъдат изгубени."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Да се спре ли записването?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Записаното съдържание ще бъде запазено."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Записването на „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ ще бъде спряно, защото е в конфликт с тази програма. Записаното съдържание ще бъде запазено."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Записът е насрочен, но има конфликти"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Записването започна, но има конфликти"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ ще се запише."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Същата програма вече е насрочена за записване в <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Вече записахте"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Тази програма вече е записана. Тя е налична в библиотеката на устройството за дигитален видеозапис."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Записването на поредицата е насрочено"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">За „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ са насрочени <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записа.</item>
+      <item quantity="one">За „<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“ е насрочен <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> запис.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">За „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ са насрочени <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записа. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> епизода няма да бъдат записани поради конфликти.</item>
+      <item quantity="one">За „<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“ е насрочен <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> запис. Епизодът няма да бъде записан поради конфликти.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">За „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ са насрочени <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записа. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизода от тази и от друга поредица няма да бъдат записани поради конфликти.</item>
+      <item quantity="one">За „<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“ е насрочен <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> запис. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> епизода от тази и от друга поредица няма да бъдат записани поради конфликти.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">За „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ са насрочени <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записа. 1 епизод от друга поредица няма да бъде записан поради конфликти.</item>
+      <item quantity="one">За „<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“ е насрочен <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> запис. 1 епизод от друга поредица няма да бъде записан поради конфликти.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">За „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ са насрочени <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записа. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизода от друга поредица няма да бъдат записани поради конфликти.</item>
+      <item quantity="one">За „<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“ е насрочен <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> запис. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> епизода от друга поредица няма да бъдат записани поради конфликти.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Записаната програма не е намерена."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Сродни записи"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Няма описание на програмата)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d записа</item>
       <item quantity="one">%1$d запис</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Да се спре ли записването на поредицата?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Записаните епизоди ще останат налице в библиотеката на устройството за дигитален видеозапис."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Спиране"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"В момента не се излъчва нито един епизод."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Няма налични епизоди.\nТе ще бъдат записани, когато са налице."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d минути)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Днес: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Утре: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Рейтинг"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Записани програми"</string>
 </resources>
diff --git a/res/values-bn-v23/strings.xml b/res/values-bn-rBD-v23/strings.xml
similarity index 100%
rename from res/values-bn-v23/strings.xml
rename to res/values-bn-rBD-v23/strings.xml
diff --git a/res/values-bn/arrays.xml b/res/values-bn-rBD/arrays.xml
similarity index 100%
rename from res/values-bn/arrays.xml
rename to res/values-bn-rBD/arrays.xml
diff --git a/res/values-bn/rating_system_strings.xml b/res/values-bn-rBD/rating_system_strings.xml
similarity index 100%
rename from res/values-bn/rating_system_strings.xml
rename to res/values-bn-rBD/rating_system_strings.xml
diff --git a/res/values-bn/strings.xml b/res/values-bn-rBD/strings.xml
similarity index 77%
rename from res/values-bn/strings.xml
rename to res/values-bn-rBD/strings.xml
index 52938ab..83e2825 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"মোনো"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"স্টিরিও"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"খেলার নিয়ন্ত্রণগুলি"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"সাম্প্রতিক চ্যানেলগুলি"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"চ্যানেলগুলি"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"টিভি বিকল্পগুলি"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP বিকল্পগুলি"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"এই চ্যানেলটির জন্য প্লে নিয়ন্ত্রণগুলি অনুপলব্ধ"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"প্লে করুন বা বিরাম দিন"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"দ্রুত ফরওয়ার্ড"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"সাবটাইটেলগুলি"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"প্রদর্শন মোড"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"চালু"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"বন্ধ"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"একাধিক-অডিও"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"আরো চ্যানেল পান"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"সেটিংস"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"উৎস"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"সোয়াইপ করুন"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"চালু"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"বন্ধ"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"আওয়াজ"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"প্রধান"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP উইন্ডো"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"লেআউট"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"ডানদিকে নীচে"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ডানদিকে শীর্ষে"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"বামদিকে শীর্ষে"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"বামদিকে নীচে"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"পাশাপাশি"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"আকার"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"বড়"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"ক্ষুদ্র"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"ইনপুট উৎস"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (অ্যান্টেনা/কেবল)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"কোনো প্রোগ্রাম তথ্য নেই"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"কোনো তথ্য নেই"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"অবরুদ্ধ চ্যানেল"</string>
-    <string name="default_language" msgid="4122326459624337928">"অজানা ভাষা"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"অজানা ভাষা"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"সাবটাইটেল %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"সাবটাইটেলগুলি"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"বন্ধ করুন"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ফর্ম্যাটিং কাস্টমাইজ করুন"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"এর ভিত্তিতে গোষ্ঠীভুক্ত করুন"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"এই প্রোগ্রামটি অবরুদ্ধ করা হয়েছে"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"এই প্রোগ্রামটিতে কোনও রেটিং দেওয়া হয়নি"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"এই প্রোগ্রামটি <xliff:g id="RATING">%1$s</xliff:g> রেট প্রাপ্ত৷"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ইনপুটটি অটো-স্ক্যান সমর্থন করে না"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' এর জন্য স্বয়ংক্রিয়-স্ক্যান শুরু করা যায়নি"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$dটি চ্যানেল যোগ করা হয়েছে</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"কোনো চ্যানেল যোগ করা হয়নি"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ট্যিউনার"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"অভিভাবকীয় নিয়ন্ত্রণগুলি"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"চালু করুন"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"বন্ধ করুন"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"অন্যান্য দেশ"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"একটিও নেই"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"কোনো কিছুই নেই"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"রেটিং দেওয়া হয়নি"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"রেটিং ছাড়া প্রোগ্রাম ব্লক করুন"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"কোনো কিছুই নেই"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"উচ্চ মাত্রার বিধিনিষেধগুলি"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"মাঝারি মাত্রার বিধিনিষেধগুলি"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"এই চ্যানেলটি দেখতে আপনার পিন লিখুন"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"এই প্রোগ্রামটি দেখতে আপনার পিন লিখুন"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"এই প্রোগ্রামটি <xliff:g id="RATING">%1$s</xliff:g> রেটপ্রাপ্ত। এই প্রোগ্রামটি দেখার জন্য আপনার PIN লিখুন।"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"এই প্রোগ্রামটিতে কোনও রেটিং দেওয়া হয়নি এটি দেখতে আপনার পিন লিখুন"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"আপনার পিন লিখুন"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"অভিভাবকীয় নিয়ন্ত্রণগুলি সেট করতে, একটি পিন তৈরি করুন"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"নতুন পিন লিখুন"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"এই PINটি ভুল ছিল৷ আবার চেষ্টা করুন৷"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"আবার চেষ্টা করুন, পিন মেলেনি"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"আপনার ডাক পিন কোড লিখুন৷"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Live TV অ্যাপটি টিভি চ্যানেলগুলির প্রোগ্রামের সম্পূর্ণ নির্দেশিকা প্রদান করার জন্য ডাক পিন কোড ব্যবহার করবে৷"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"আপনার ডাক পিন কোড লিখুন"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"অবৈধ ডাক পিন কোড"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"সেটিংস"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"চ্যানেল তালিকা কাস্টমাইজ করুন"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"আপনার প্রোগ্রাম গাইডের জন্য চ্যানেলগুলি নির্বাচন করুন"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"চ্যানেলের উৎসগুলি"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"নতুন চ্যানেলগুলি উপলব্ধ"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"অভিভাবকীয় নিয়ন্ত্রণগুলি"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"টাইমশিফ্ট"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"দেখার সময় রেকর্ড করুন সুতারং আপনি লাইভ প্রোগ্রামগুলিকে বিরাম দিতে বা রিওয়াইন্ড করতে পারেন৷\nসতর্কতা: সঞ্চয়স্থানের বেশি পরিমাণে ব্যবহার করার ফলে অভ্যন্তরীণ সঞ্চয়স্থানের কর্মক্ষমতা হ্রাস করতে পারে৷"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"মুক্ত উৎস লাইসেন্সগুলি"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"মুক্ত উৎস লাইসেন্সগুলি"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"প্রতিক্রিয়া পাঠান"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"সংস্করণ"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"এই চ্যানেলটিকে দেখতে, ডানদিকে চাপুন এবং আপনার পিন লিখুন"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"এই প্রোগ্রামটি দেখতে, ডানদিকে চাপুন এবং আপনার পিন লিখুন"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"এই প্রোগ্রামটিতে কোনও রেটিং দেওয়া হয়নি।\nএটি দেখতে ডান দিকের বোতামটি টিপুন এবং আপনার পিন লিখুন"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"এই প্রোগ্রামটি <xliff:g id="RATING">%1$s</xliff:g> রেট প্রাপ্ত৷\nএই প্রোগ্রামটি দেখতে, ডানদিকে চাপুন এবং আপনার পিন লিখুন"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"এই চ্যানেলটি দেখতে, ডিফল্ট লাইভ টিভি অ্যাপ্লিকেশানটি ব্যবহার করুন৷"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"এই প্রোগ্রামটি দেখতে, ডিফল্ট লাইভ টিভি অ্যাপ্লিকেশানটি ব্যবহার করুন৷"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"এই প্রোগ্রামটিতে কোনও রেটিং দেওয়া হয়নি\nডিফল্ট লাইভ TV অ্যাপে এটি দেখুন।"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"এই প্রোগ্রামটি <xliff:g id="RATING">%1$s</xliff:g> রেট প্রাপ্ত৷\nএই প্রোগ্রামটি দেখতে, ডিফল্ট লাইভ টিভি অ্যাপ্লিকেশানটি ব্যবহার করুন৷"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"প্রোগ্রামটি অবরুদ্ধ"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"এই প্রোগ্রামটিতে কোনও রেটিং দেওয়া হয়নি"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"এই প্রোগ্রামটি <xliff:g id="RATING">%1$s</xliff:g> রেট প্রাপ্ত৷"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"কেবলমাত্র অডিও"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"সিগন্যাল দুর্বল"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"টিভি মেনু অ্যাক্সেস করতে "<b>"নির্বাচন করুন টিপুন"</b>"৷"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"কোনো TV ইনপুট খুঁজে পাওয়া যায়নি"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV ইনপুট খুঁজে পাওয়া যায়নি"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP সমর্থিত নয়"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP এর সাথে দেখানো যেতে পারে এমন কোনো উপলব্ধ ইনপুট নেই"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"টিউনারের প্রকারটি উপযুক্ত নয়; টিউনার প্রকারের টিভি ইনপুটের জন্য দয়া করে লইভ চ্যানেলগুলি অ্যাপ্লিকেশানটি লঞ্চ করুন৷"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"টিউন করা ব্যর্থ হয়েছে"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"এই ক্রিয়াটিকে চালনা করার জন্য কোনো অ্যাপ্লিকেশান পাওয়া যায়নি৷"</string>
@@ -226,12 +217,14 @@
       <item quantity="one">%1$dটি রেকর্ডিংয়ের সময় নির্ধারিত হয়েছে</item>
       <item quantity="other">%1$dটি রেকর্ডিংয়ের সময় নির্ধারিত হয়েছে</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"রেকর্ডিং বাতিল করুন"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"রেকডিং বন্ধ করুন"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"দেখুন"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"শুরু থেকে প্লে করুন"</string>
-    <string name="dvr_detail_resume_play" msgid="875591300274416373">"পুনরায় প্লে করুন"</string>
+    <string name="dvr_detail_resume_play" msgid="875591300274416373">"আবার প্লে করুন"</string>
     <string name="dvr_detail_delete" msgid="4535881013528321898">"মুছুন"</string>
     <string name="dvr_detail_series_delete" msgid="4831926831670312674">"রেকডিংগুলি মুছুন"</string>
-    <string name="dvr_detail_series_resume" msgid="6935136228671386246">"পুনরায় শুরু করুন"</string>
+    <string name="dvr_detail_series_resume" msgid="6935136228671386246">"আবার শুরু করুন"</string>
     <string name="dvr_detail_series_season_title" msgid="5474850936497854790">"সিজন <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>"</string>
     <string name="dvr_detail_view_schedule" msgid="7137536927421904426">"সময়সূচী দেখুন"</string>
     <string name="dvr_detail_read_more" msgid="2588920758094498544">"আরো পড়ুন"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"যখন একই সময়ে অনেকগুলি প্রোগ্রাম রেকর্ড করা হয় তখন শুধুমাত্র উচ্চ অগ্রাধিকারযুক্ত প্রোগ্রামগুলিকে রেকর্ড করা হবে৷"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"সংরক্ষণ করুন"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"একবার করা রেকর্ডিংগুলিতে সর্বোচ্চ অগ্রাধিকার রয়েছে"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"বাতিল করুন"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"বাতিল করুন"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"মুছে দিন"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"থামান"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"রেকডিং এর সময়সূচী দেখুন"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"শুধুমাত্র এই প্রোগ্রামটি"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"বরং এটি রেকর্ড করুন"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"এই রেকর্ডিং বাতিল করুন"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"এখনই দেখুন"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"রেকডিংগুলি মুছুন..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"রেকর্ড করা যাবে"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"রেকর্ডিংএর সময় নির্ধারিত হয়েছে"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"রেকর্ডিং দ্বন্দ্ব"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"রেকর্ড করা হচ্ছে"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"রেকডিং করা গেল না"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"রেকর্ডিংয়ের সময়সূচীগুলি তৈরি করতে প্রোগ্রামগুলি পড়া হচ্ছে"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"প্রোগ্রামগুলি পড়া হচ্ছে"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"প্রোগ্রামগুলি পড়া হচ্ছে"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"সাম্প্রতিক রেকর্ডিংগুলি দেখুন"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> এর রেকর্ডিং অসম্পূর্ণ।"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> এবং <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> এর রেকর্ডিং সম্পূর্ণ।"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> এবং <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> এর রেকর্ডিং অসম্পূর্ণ।"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"অপর্যাপ্ত সঞ্চয়স্থান থাকার কারণে <xliff:g id="PROGRAMNAME">%1$s</xliff:g> এর রেকর্ডিং সম্পূর্ণ হয়নি।"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"অপর্যাপ্ত সঞ্চয়স্থান থাকার কারণে <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> এবং <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> এর রেকর্ডিং সম্পূর্ণ হয়নি।"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"অপর্যাপ্ত সঞ্চয়স্থান থাকার কারণে <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> এবং <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> এর রেকর্ডিং সম্পূর্ণ হয়নি।"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR এর আরো সঞ্চয়স্থান দরকার"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"আপনি DVR এর মাধ্যমে প্রোগ্রাম রেকর্ড করতে পারবেন৷ তবে DVR কাজ করার জন্য আপনার ডিভাইসে এখন যথেষ্ঠ সঞ্চয়স্থান নেই৷ অনুগ্রহ করে <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB বা তার থেকে বড় আকারের কোনো বাহ্যিক ডিভাইসের সাথে সংযোগ করুন এবং ডিভাইসের সঞ্চয়স্থান হিসাবে ফর্ম্যাট করতে পদক্ষেপগুলি অনুসরণ করুন৷"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"আপনি DVR এর মাধ্যমে প্রোগ্রাম রেকর্ড করতে পারবেন৷ তবে DVR কাজ করার জন্য আপনার ডিভাইসে এখন যথেষ্ঠ সঞ্চয়স্থান নেই৷ অনুগ্রহ করে <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB বা তার থেকে বড় আকারের কোনো বাহ্যিক ডিভাইসের সাথে সংযোগ করুন এবং ডিভাইসের সঞ্চয়স্থান হিসাবে ফর্ম্যাট করতে পদক্ষেপগুলি অনুসরণ করুন৷"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"পর্যাপ্ত সঞ্চয়স্থান নেই"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"এখানে পর্যাপ্ত সঞ্চয়স্থান না থাকার কারণে এই প্রোগ্রামটিকে রেকর্ড করা যাবে না৷ বিদ্যমান কিছু রেকর্ডিং মোছার চেষ্টা করুন৷"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"সঞ্চয়স্থান অনুপস্থিত"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR দ্বারা ব্যবহৃত কিছু সঞ্চয়স্থান অনুপস্থিত৷ DVR পুনরায় সক্ষম করার আগে অনুগ্রহ করে আপনার আগে ব্যবহার করা বাহ্যিক ড্রাইভ সংযোগ করুন৷ অথবা, যদি সঞ্চয়স্থানটি আর উপলব্ধ না থাকে তবে আপনি সেটিকে মুছে দিতে পারবেন৷"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"সঞ্চয়স্থান মুছতে চান?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"আপনার রেকর্ড করা সমস্ত সামগ্রী এবং সময়সূচী মুছে যাবে৷"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"রেকর্ড করা থামাবেন?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"রেকর্ড করা সামগ্রী সংরক্ষণ করা হবে৷"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"এই প্রোগ্রামের সাথে রেকডিং দ্বন্দ্ব থাকায় <xliff:g id="PROGRAMNAME">%1$s</xliff:g> এর রেকর্ডিং বন্ধ হবে। রেকর্ড করা সামগ্রী সংরক্ষিত হবে।"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"রেকর্ডিংয়ের যে সময় নির্ধারিত করা হয়েছে তাতে অন্যদের সমসয়ের সাথে বিরোধ ঘটাতে পারে।"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"রেকর্ডিং শুরু হয়েছে কিন্তু দ্বন্দ্বগুলি রয়েছে"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> রেকর্ড করা হবে৷"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"একই প্রোগ্রাম ইতিমধ্যেই <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> এ রেকর্ড করার জন্য নির্ধারণ করা হয়েছে।"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"ইতিমধ্যে রেকর্ড করা হয়েছে"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"এই প্রোগ্রামটি ইতিমধ্যে রেকর্ড করা হয়েছে। এটি DVR লাইব্রেরিতে উপলব্ধ।"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"সিরিজ রেকর্ডিংয়ের সময় নির্ধারিত হয়েছে"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে।</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে।</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে। বিরোধগুলির কারণে এগুলির মধ্যে <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>টি পর্ব রেকর্ড করা যাবে না৷</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে। বিরোধগুলির কারণে এগুলির মধ্যে <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>টি পর্ব রেকর্ড করা যাবে না৷</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে। বিরোধগুলির কারণে এটি এবং অন্য সিরিজের <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>টি পর্ব রেকর্ড করা যাবে না৷</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে। বিরোধগুলির কারণে এটি এবং অন্য সিরিজের <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>টি পর্ব রেকর্ড করা যাবে না৷</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে৷ বিরোধগুলির কারণে অন্য সিরিজের ১টি পর্ব রেকর্ড করা যাবে না৷</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে৷ বিরোধগুলির কারণে অন্য সিরিজের ১টি পর্ব রেকর্ড করা যাবে না৷</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে। বিরোধগুলির কারণে অন্য সিরিজের <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>টি পর্ব রেকর্ড করা যাবে না৷</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> এর জন্য <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>টি রেকর্ডিংয়ের সময়সূচি নির্ধারণ করা হয়েছে। বিরোধগুলির কারণে অন্য সিরিজের <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>টি পর্ব রেকর্ড করা যাবে না৷</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"রেকর্ড করা প্রোগ্রাম খুঁজে পাওয়া যায়নি৷"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"সম্পর্কিত রেকর্ডিং"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(প্রোগ্রামের কোনো বিবরণ নেই)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$dটি রেকর্ডিং</item>
       <item quantity="other">%1$dটি রেকর্ডিং</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"সিরিজি রেকর্ড করা বন্ধ করতে চান?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"রেকর্ড করা পর্বগুলি DVR লাইব্রেরিতে উপলব্ধ থাকবে৷"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"বন্ধ করুন"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"এখন কোনো পর্বের সম্প্রচার করা হচ্ছে না।"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"কোনো পর্ব উপলব্ধ নেই।\nএকবার উপলব্ধ হলে সেগুলিকে রেকর্ড করা হবে।"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d মিনিট)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"আজ <xliff:g id="TIME_RANGE">%1$s</xliff:g> টায়"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"আগামীকাল <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"স্কোর"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"রেকর্ড করা প্রোগ্রামগুলি"</string>
 </resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 3ab61ff..e26cc99 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"estèreo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Controls de reproducció"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Canals recents"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Canals"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opcions de TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opcions de PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Els controls de reproducció no estan disponibles en aquest canal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Reprodueix o atura"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avança ràpidament"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Subtítols"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Mode visualitz."</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Activada"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Desactivada"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multiàudio"</string>
-    <string name="options_item_more_channels" msgid="971040969622943300">"Obtén més canals"</string>
+    <string name="options_item_more_channels" msgid="971040969622943300">"Troba més canals"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Configuració"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Font"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Canvia"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Activada"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Desactivada"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"So"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principal"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Finestra PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Disseny"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"A baix a dreta"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"A dalt a dreta"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"A dalt a esq."</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"A baix a esq."</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"En paral·lel"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Mida"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Gran"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Petita"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Font d\'entrada"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Televisió (antena/cable)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"No hi ha informació del programa"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"No hi ha informació"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Canal bloquejat"</string>
-    <string name="default_language" msgid="4122326459624337928">"Idioma desconegut"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Idioma desconegut"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtítols en %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Subtítols ocults"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Desactivat"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personalitza format"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Agrupa per"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Aquest programa està bloquejat"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Aquest programa no s\'ha classificat"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Aquest programa està classificat com a <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"L\'entrada no és compatible amb la cerca automàtica."</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"No es pot iniciar la cerca automàtica de: <xliff:g id="TV_INPUT">%s</xliff:g>."</string>
@@ -92,7 +74,6 @@
       <item quantity="one">S\'ha afegit %1$d canal</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"No s\'ha afegit cap canal."</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sintonitzador"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Controls dels pares"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Activats"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Desactivats"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Altres països"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Cap"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Cap"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Sense classificar"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloqueja prog. sense classificar"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Cap"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restriccions altes"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restricc. mitjanes"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Introducció del PIN per mirar aquest canal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Introducció del PIN per mirar aquest programa"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Aquest programa està classificat com a <xliff:g id="RATING">%1$s</xliff:g>. Introdueix el PIN per mirar-lo"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Aquest programa no s\'ha classificat. Introdueix el PIN per veure\'l."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Introducció del PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Per definir els controls dels pares, crea un PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Introdueix el PIN nou"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"El PIN era incorrecte. Torna-ho a provar."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Torna-ho a provar. El PIN no coincideix."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Introdueix el codi postal."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"L\'aplicació TV en directe farà servir el codi postal per oferir una programació completa dels canals de televisió."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Introdueix el codi postal"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"El codi postal no és vàlid"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Configuració"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalitza la llista de canals"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Tria canals per a la programació"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Fonts de canals"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nous canals disponibles"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Controls parentals"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Desplaçament temporal"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Enregistra els programes en directe mentre els mires per poder-los posar en pausa o rebobinar.\nAdvertiment: aquesta opció suposa un ús intens de l\'emmagatzematge intern, i això en pot disminuir la vida útil."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Llicències de programari lliure"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Llicències de programari lliure"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Envia suggeriments"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versió"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Per veure aquest canal, prem el botó dret i introdueix el PIN."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Per veure aquest programa, prem el botó dret i introdueix el PIN."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Aquest programa no s\'ha classificat.\nPer veure\'l, prem el botó dret i introdueix el PIN."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Aquest programa està classificat com a <xliff:g id="RATING">%1$s</xliff:g>.\nPer veure\'l, prem el botó dret i introdueix el PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Per mirar aquest canal, fes servir l\'aplicació Televisió en directe predeterminada."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Per mirar aquest programa, fes servir l\'aplicació Televisió en directe predeterminada."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Aquest programa no s\'ha classificat.\nPer veure\'l, utilitza l\'aplicació Televisió en directe predeterminada."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Aquest programa té la classificació següent: <xliff:g id="RATING">%1$s</xliff:g>.\nPer mirar-lo, fes servir l\'aplicació Televisió en directe predeterminada."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"El programa està bloquejat."</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Aquest programa no s\'ha classificat"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Aquest programa està classificat com a <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Només àudio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"El senyal és feble"</string>
@@ -169,8 +162,8 @@
     </plurals>
     <string name="setup_input_no_channels" msgid="1669327912393163331">"No hi ha cap canal disponible"</string>
     <string name="setup_input_new" msgid="3337725672277046798">"Nou"</string>
-    <string name="setup_input_setup_now" msgid="1772000402336958967">"No s\'ha configurat"</string>
-    <string name="setup_store_action_title" msgid="4083402039720973414">"Obtén més fonts"</string>
+    <string name="setup_input_setup_now" msgid="1772000402336958967">"No configurat"</string>
+    <string name="setup_store_action_title" msgid="4083402039720973414">"Troba més fonts"</string>
     <string name="setup_store_action_description" msgid="6820482635042445297">"Navega per les aplicacions que ofereixen TV en directe"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"Hi ha noves fonts de canals disponibles"</string>
     <string name="new_sources_description" msgid="749649005588426813">"Les noves fonts de canals tenen canals per oferir.\nConfigura-les ara o fes-ho més tard des de la seva secció de configuració."</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Prem SELECCIONA"</b>" per accedir al menú de TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"No s\'ha trobat cap entrada de televisió"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"No es troba l\'entrada de televisió"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"No s\'admet la funció PIP"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"No hi ha cap entrada disponible que es pugui mostrar amb PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"El sintonitzador no és apte; inicia l\'aplicació Canals en directe per accedir a l\'entrada del sintonitzador."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"No s\'ha pogut sintonitzar"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"No s\'ha trobat cap aplicació per processar aquesta acció."</string>
@@ -191,7 +182,7 @@
     <string name="msg_back_key_guide" msgid="7404682718828721924">"La tecla ENRERE és per als dispositius connectats. Prem el botó INICI per sortir."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Canals en directe necessita permís per consultar les programacions de TV."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Configura les teves fonts"</string>
-    <string name="setup_sources_description" msgid="5695518946225445202">"L\'aplicació TV en directe combina l\'experiència dels canals de televisió tradicionals amb els canals de reproducció en temps real proporcionats per les aplicacions. \n\nPer començar, configura les fonts de canals que ja hi ha instal·lades. També pots navegar per Google Play Store per descobrir més aplicacions que ofereixin TV en directe."</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"TV en directe combina l\'experiència dels canals de televisió tradicionals amb els canals de reproducció en temps real proporcionats per les aplicacions. \n\nPer començar, configura les fonts de canals que ja hi ha instal·lades. També pots navegar per Google Play Store per descobrir més aplicacions que ofereixin TV en directe."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Enregistraments i horaris"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minuts"</string>
     <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 minuts"</string>
@@ -224,6 +215,8 @@
       <item quantity="other">%1$d enregist. programats</item>
       <item quantity="one">%1$d enregistr. programat</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancel·la l\'enregistrament"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Atura l\'enregistrament"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Reprodueix"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Reprodueix des del principi"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Reprèn la reproducció"</string>
@@ -256,9 +249,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Quan hi hagi massa programes per enregistrar a la mateixa hora, només s\'enregistraran els que tinguin una prioritat més elevada."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Desa"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Els enregistraments únics tenen la prioritat més alta"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancel·la"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancel·la"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"No recordis"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Atura"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Mostra programa d\'enregistrament"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Només aquest programa"</string>
@@ -268,25 +258,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Enregistra aquest programa"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancel·la aquest enregistrament"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Mira ara"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Suprimeix els enregistraments…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Enregistrable"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Enregistrament programat"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Conflicte d\'enregistrament"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"S\'està enregistrant"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Error d\'enregistrament"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"S\'estan llegint els programes per crear programacions d\'enregistrament"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"S\'estan llegint els programes"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"S\'estan llegint els programes"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Mostra els enregistraments recents"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"L\'enregistrament  del programa <xliff:g id="PROGRAMNAME">%1$s</xliff:g> no s\'ha completat."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Els enregistraments dels programes <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> i <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> no s\'han completat."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Els enregistraments dels programes <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> i <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> no s\'han completat."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"L\'enregistrament del programa <xliff:g id="PROGRAMNAME">%1$s</xliff:g> no s\'ha completat perquè no hi ha prou espai d\'emmagatzematge."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Els enregistraments dels programes <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> i <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> no s\'han completat perquè no hi ha prou espai d\'emmagatzematge."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Els enregistraments dels programes <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> i <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> no s\'han completat perquè no hi ha prou espai d\'emmagatzematge."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"El DVR necessita més emmagatzematge"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Podràs· enregistrar· programes· amb· el· DVR.· No· obstant· això,· en· aquests· moments· no· tens· prou· emmagatzematge· al· dispositiu· perquè· el· DVR· pugui· funcionar.· Connecta· una· unitat· externa· que· tingui· com· a· mínim· <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB· d\'espai· disponible· i· segueix· els· passos· per· formatar-la· com· a· unitat· d\'emmagatzematge· del· dispositiu."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Podràs· enregistrar· programes· amb· el· DVR.· No· obstant· això,· en· aquests· moments· no· tens· prou· emmagatzematge· al· dispositiu· perquè· el· DVR· pugui· funcionar.· Connecta· una· unitat· externa· que· tingui· com· a· mínim· <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB· d\'espai· disponible· i· segueix· els· passos· per· formatar-la· com· a· unitat· d\'emmagatzematge· del· dispositiu."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"No hi ha prou espai d\'emmagatzematge"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Aquest programa no s\'enregistrarà perquè no hi ha prou espai d\'emmagatzematge. Prova de suprimir algun dels enregistraments actuals."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Falta el dispositiu d\'emmagatzematge"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Falta contingut emmagatzemat pel DVR. Connecta la unitat externa que utilitzaves abans per tornar a activar el DVR. Si el dispositiu d\'emmagatzematge ja no està disponible, pots optar perquè s\'oblidi."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Vols que s\'oblidi el dispositiu d\'emmagatzematge?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Tot el contingut i totes les agendes que tinguis desades es perdran."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Vols aturar l\'enregistrament?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"El contingut enregistrat es desarà."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"L\'enregistrament de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> s\'aturarà perquè entra en conflicte amb aquest programa. El contingut enregistrat es desarà."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Hi ha un enregistrament programat, però té conflictes"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"L\'enregistrament ha començat, però té conflictes"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> s\'enregistrarà."</string>
@@ -304,17 +297,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Ja s\'ha programat l\'enregistrament d\'aquest programa per a les <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Ja s\'ha enregistrat"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Aquest programa ja s\'ha enregistrat. El trobaràs a la biblioteca de DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"S\'ha programat l\'enregistrament de la sèrie"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">S\'han programat <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistraments de la sèrie <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">S\'ha programat <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> enregistrament de la sèrie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">S\'han programat <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistraments de la sèrie <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> no s\'enregistraran a causa d\'un conflicte.</item>
+      <item quantity="one">S\'ha programat <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> enregistrament de la sèrie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. No s\'enregistrarà a causa d\'un conflicte.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">S\'han programat <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistraments de la sèrie <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodis d\'aquesta i d\'altres sèries no s\'enregistraran a causa d\'un conflicte.</item>
+      <item quantity="one">S\'ha programat <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> enregistrament de la sèrie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodis d\'aquesta i d\'altres sèries no s\'enregistraran a causa d\'un conflicte.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">S\'han programat <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistraments de la sèrie <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. No s\'enregistrarà un episodi d\'una altra sèrie a causa d\'un conflicte.</item>
+      <item quantity="one">S\'ha programat <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> enregistrament de la sèrie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. No s\'enregistrarà un episodi d\'una altra sèrie a causa d\'un conflicte.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">S\'han programat <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistraments de la sèrie <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. No s\'enregistraran <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodis d\'altres sèries a causa d\'un conflicte.</item>
+      <item quantity="one">S\'ha programat <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> enregistrament de la sèrie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. No s\'enregistraran <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodis d\'altres sèries a causa d\'un conflicte.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"El programa enregistrat no s\'ha trobat."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Enregistraments relacionats"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Cap descripció del programa)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d enregistraments</item>
       <item quantity="one">%1$d enregistrament</item>
@@ -334,6 +339,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Vols aturar l\'enregistrament de la sèrie?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Els episodis enregistrats continuaran estant disponibles a la biblioteca de DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Atura"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"En aquest moment no s\'està emetent cap episodi en directe."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"No hi ha episodis disponibles.\nS\'enregistraran quan estiguin disponibles."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minuts)</item>
@@ -345,4 +351,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Avui, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Demà, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Puntuació"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programes enregistrats"</string>
 </resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 6dac175..c69c38f 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Ovládání přehrávání"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Poslední kanály"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanály"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Možnosti TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Možnosti PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Ovládací prvky přehrávání pro tento kanál nejsou k dispozici"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Přehrát nebo pozastavit"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Přetočit vpřed"</string>
@@ -30,42 +29,24 @@
     <string name="play_controls_description_skip_next" msgid="1603587562124694592">"Další"</string>
     <string name="play_controls_description_skip_previous" msgid="3858447678278021381">"Předchozí"</string>
     <string name="channels_item_program_guide" msgid="2889807207930678418">"Programový průvodce"</string>
-    <string name="channels_item_setup" msgid="6557412175737379022">"Jsou dostupné nové kanály"</string>
+    <string name="channels_item_setup" msgid="6557412175737379022">"Dostupné nové kanály"</string>
     <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"Spustit aplikaci <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Skryté titulky"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Režim zobrazení"</string>
-    <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Zapnuto"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Vypnuto"</string>
+    <string name="options_item_pip" msgid="3951350386626879645">"Obraz v obraze"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Vícekanál. zvuk"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Další kanály"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Nastavení"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Zdroj"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Zaměnit"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Zapnuto"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Vypnuto"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Zvuk"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Hlavní"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Okno PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Rozvržení"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Vpravo dole"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Vpravo nahoře"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Vlevo nahoře"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Vlevo dole"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Vedle sebe"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Rozměry"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Velké"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Malé"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Zdroj vstupu"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (anténa/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Žádné informace o programu"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Žádné informace"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blokovaný kanál"</string>
-    <string name="default_language" msgid="4122326459624337928">"Neznámý jazyk"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Neznámý jazyk"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Skryté titulky: %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Skryté titulky"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Vypnuto"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Nastavit formátování"</string>
-    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Zadání sys. předvoleb pro skryté titulky"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Systémová nastavení pro skryté titulky"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Režim zobrazení"</string>
     <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Vícekanál. zvuk"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"mono"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Seskupit podle"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Tento program je blokován."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Tento program nemá hodnocení"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Tento program má hodnocení <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Vstup nepodporuje automatické vyhledávání"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Nelze spustit automatické vyhledávání vstupu <xliff:g id="TV_INPUT">%s</xliff:g>"</string>
@@ -94,7 +76,6 @@
       <item quantity="one">Byl přidán %1$d kanál</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Bylo přidáno 0 kanálů"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Rodičovská ochrana"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Zapnuto"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Vypnuto"</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Ostatní země"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Žádný"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Žádný"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Bez hodnocení"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokovat programy bez hodnocení"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Žádné"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Vysoké omezení"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Střední omezení"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Chcete-li sledovat tento kanál, zadejte kód PIN."</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Chcete-li sledovat tento program, zadejte kód PIN."</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Tento program má hodnocení <xliff:g id="RATING">%1$s</xliff:g>. Chcete-li jej sledovat, zadejte kód PIN."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Tento program nemá hodnocení. Chcete-li ho sledovat, zadejte kód PIN."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Zadání kódu PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Chcete-li nastavit rodičovskou kontrolu, vytvořte kód PIN."</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Zadejte nový PIN"</string>
@@ -139,22 +123,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Kód PIN byl zadán chybně. Zkuste to znovu."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Kód PIN nesouhlasí. Zkuste to znovu."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Zadejte PSČ."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Aplikace Televize online vám na základě PSČ poskytne kompletního programového průvodce televizními kanály."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Zadejte PSČ"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Neplatné PSČ"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Nastavení"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Upravit seznam kanálů"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Vyberte kanály pro programového průvodce"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Zdroje kanálů"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"K dispozici jsou nové kanály"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Rodičovská ochrana"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Časový posun"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Umožňuje nahrávat při sledování, abyste mohli živě vysílané programy pozastavit nebo přetočit zpět.\nUpozornění: Funkce intenzivně využívá interní úložiště, a může tak snížit jeho životnost."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licence open source"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licence open source"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Odeslat zpětnou vazbu"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Verze"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Chcete-li tento kanál sledovat, stiskněte šipku vpravo a zadejte kód PIN."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Chcete-li tento program sledovat, stiskněte šipku vpravo a zadejte kód PIN."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Tento program nemá hodnocení.\nChcete-li ho sledovat, stiskněte šipku vpravo a zadejte kód PIN."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Tento program má hodnocení <xliff:g id="RATING">%1$s</xliff:g>.\nChcete-li tento program sledovat, stiskněte šipku vpravo a zadejte kód PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Chcete-li tento kanál sledovat, použijte výchozí aplikaci Live TV."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Chcete-li tento program sledovat, použijte výchozí aplikaci Live TV."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Tento program nemá hodnocení.\nChcete-li ho sledovat, použijte výchozí aplikaci Live TV."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Tento program má hodnocení <xliff:g id="RATING">%1$s</xliff:g>.\nChcete-li tento program sledovat, použijte výchozí aplikaci Live TV."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Program je blokován"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Tento program nemá hodnocení"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Tento program má hodnocení <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Pouze zvuk"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Slabý signál"</string>
@@ -189,8 +182,6 @@
     <string name="intro_description" msgid="7806473686446937307">"Chcete-li získat přístup k nabídce TV, "<b>"stiskněte SELECT"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nebyl nalezen žádný televizní vstup."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Televizní vstup nebyl nalezen."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Funkce PIP není podporována."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Není k dispozici vstup, který lze zobrazovat pomocí PIP."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Typ tuneru není vhodný. Pro TV vstup typu tuneru spusťte aplikaci Televize online."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Ladění se nezdařilo."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Aplikace potřebná k provedení této akce nebyla nalezena."</string>
@@ -244,6 +235,8 @@
       <item quantity="other">%1$d naplánovaných nahrávek</item>
       <item quantity="one">%1$d naplánovaná nahrávka</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Zrušit nahrávání"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Zastavit nahrávání"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Přehrát"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Přehrát od začátku"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Pokračovat v přehrávání"</string>
@@ -278,9 +271,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Když naplánujete nahrávání příliš mnoha programů, budou nahrány pouze programy s vyšší prioritou."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Uložit"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Jednorázová nahrávání mají nejvyšší prioritu"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Zrušit"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Zrušit"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Zapomenout"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Zastavit"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Zobrazit plán nahrávání"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Pouze tento program"</string>
@@ -290,25 +280,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Místo toho nahrát tento program"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Zrušit toto nahrávání"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Sledovat"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Smazat nahraný obsah…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Lze nahrát"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Nahrávání je naplánováno"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Konflikt nahrávání"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Nahrávání"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Nahrávání se nezdařilo"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Načítání programů za účelem vytvoření plánů nahrávání"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Načítání programů"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Načítání programů"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Zobrazit poslední nahrávky"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Program <xliff:g id="PROGRAMNAME">%1$s</xliff:g> se nepodařilo nahrát celý."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Programy <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> a <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> se nepodařilo nahrát celé."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Programy <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> a <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> se nepodařilo nahrát celé."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Nahrávání programu <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nebylo dokončeno z důvodu nedostatku místa v úložišti."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Nahrávání programů <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> a <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nebylo dokončeno z důvodu nedostatku místa v úložišti."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Nahrávání programů <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> a <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nebylo dokončeno z důvodu nedostatku místa v úložišti."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR potřebuje víc místa"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Programy bude možné nahrát pomocí DVR. Ve vašem zařízení však momentálně není dost místa, a DVR proto nebude fungovat. Zapojte externí úložiště o velikosti minimálně <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB a podle pokynů jej naformátujte jako úložiště zařízení."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Programy bude možné nahrát pomocí DVR. Ve vašem zařízení však momentálně není dost místa, a DVR proto nebude fungovat. Zapojte externí úložiště o velikosti minimálně <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB a podle pokynů jej naformátujte jako úložiště zařízení."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Nedostatek místa"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Tento program nebude nahrán z důvodu nedostatku místa. Zkuste smazat část nahraného obsahu."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Úložiště není dostupné"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Část úložiště, které využívá DVR, není dostupná. Před opětovnou aktivací DVR připojte externí disk. Pokud úložiště již není k dispozici, můžete jej zapomenout."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Zapomenout úložiště?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Veškerý nahraný obsah a plány nahrávání budou smazány."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Zastavit nahrávání?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Nahraný obsah bude uložen."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Nahrávání pořadu <xliff:g id="PROGRAMNAME">%1$s</xliff:g> bude zastaveno, protože je v konfliktu s tímto programem. Nahraný obsah bude uložen."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Nahrávání je naplánováno, ale obsahuje konflikty"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Nahrávání bylo zahájeno, ale obsahuje konflikty"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Nahraje se program <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -328,17 +321,39 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Nahrávání stejného programu již bylo naplánováno na <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Již nahráno"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Tento program již byl nahrán. Naleznete jej v knihovně DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Je naplánováno nahrávání pořadu"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="few">Byla naplánována <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="many">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="few">Byla naplánována <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z důvodu konfliktů některá nahrávání nebudou provedena (celkem <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>).</item>
+      <item quantity="many">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z důvodu konfliktů některá nahrávání nebudou provedena (celkem <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>).</item>
+      <item quantity="other">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z důvodu konfliktů některá nahrávání nebudou provedena (celkem <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>).</item>
+      <item quantity="one">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Z důvodu konfliktů nahrávání nebude provedeno.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="few">Byla naplánována <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z důvodu konfliktů nebudou nahrány epizody tohoto pořadu a jiných pořadů (celkem <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="many">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z důvodu konfliktů nebudou nahrány epizody tohoto pořadu a jiných pořadů (celkem <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="other">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z důvodu konfliktů nebudou nahrány epizody tohoto pořadu a jiných pořadů (celkem <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="one">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Z důvodu konfliktů nebudou nahrány epizody tohoto pořadu a jiných pořadů (celkem <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g>).</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="few">Byla naplánována <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z důvodu konfliktů nebude nahrána 1 epizoda jiného pořadu.</item>
+      <item quantity="many">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z důvodu konfliktů nebude nahrána 1 epizoda jiného pořadu.</item>
+      <item quantity="other">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z důvodu konfliktů nebude nahrána 1 epizoda jiného pořadu.</item>
+      <item quantity="one">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Z důvodu konfliktů nebude nahrána 1 epizoda jiného pořadu.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="few">Byla naplánována <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z důvodu konfliktů nebudou nahrány epizody jiných pořadů (celkem <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="many">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z důvodu konfliktů nebudou nahrány epizody jiných pořadů (celkem <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="other">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z důvodu konfliktů nebudou nahrány epizody jiných pořadů (celkem <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="one">Bylo naplánováno <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nahrávání pořadu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Z důvodu konfliktů nebudou nahrány epizody jiných pořadů (celkem <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g>).</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Nahraný program nebyl nalezen."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Související nahrávky"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Žádný popis programu)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="few">%1$d nahrávky</item>
       <item quantity="many">%1$d nahrávky</item>
@@ -362,6 +377,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Zastavit nahrávání série?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Nahrané epizody zůstanou dostupné v knihovně DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Zastavit"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Momentálně nejsou vysílány žádné epizody."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nejsou k dispozici žádné epizody.\nEpizody budou nahrány, až budou k dispozici."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="few">(%1$d minuty)</item>
@@ -375,4 +391,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Dnes v <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Zítra v <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Skóre"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Nahrané programy"</string>
 </resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index b053e77..352f4c7 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Afspilningsknapper"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Seneste kanaler"</string>
-    <string name="menu_title_options" msgid="7184594626814914022">"Tv-indstillinger"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-muligheder"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanaler"</string>
+    <string name="menu_title_options" msgid="7184594626814914022">"Indstillinger for tv"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Afspilningsstyring er ikke tilgængeligt på denne kanal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Afspil, eller sæt på pause"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Spol frem"</string>
@@ -30,38 +29,20 @@
     <string name="play_controls_description_skip_next" msgid="1603587562124694592">"Næste"</string>
     <string name="play_controls_description_skip_previous" msgid="3858447678278021381">"Forrige"</string>
     <string name="channels_item_program_guide" msgid="2889807207930678418">"Programguide"</string>
-    <string name="channels_item_setup" msgid="6557412175737379022">"Der er nye tilgængelige kanaler"</string>
+    <string name="channels_item_setup" msgid="6557412175737379022">"Nye tilgængelige kanaler"</string>
     <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"Åbn <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Undertekster"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Format"</string>
-    <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Til"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Fra"</string>
+    <string name="options_item_pip" msgid="3951350386626879645">"Integreret billede"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Flere lydspor"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Få flere kanaler"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Indstillinger"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Kilde"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Skift"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Til"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Fra"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Lyd"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Primær"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-vindue"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Nederst til højre"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Øverst til højre"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Øverst til venstre"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Nederst til venstre"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Side om side"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Størrelse"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Stor"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Lille"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Inputkilde"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Tv (antenne/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Ingen programoplysninger"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Ingen oplysninger"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blokeret kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Ukendt sprog"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Ukendt sprog"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Undertekster %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Undertekster"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Fra"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Tilpas formatering"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Gruppér efter"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Dette program er blokeret"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Dette program er ikke klassificeret"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Dette program er klassificereret som <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Dette input understøtter ikke automatisk scanning"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Automatisk scanning for \"<xliff:g id="TV_INPUT">%s</xliff:g>\" kunne ikke startes"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d kanaler blev tilføjet</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Ingen kanaler tilføjet"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Børnesikring"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Til"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Fra"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Andre lande"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ingen"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ingen"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Ikke klassificeret"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloker programmer uden klassificering"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ingen"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Høje begrænsninger"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Medium begrænsninger"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Angiv din pinkode for at se denne kanal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Angiv din pinkode for at se dette program"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Dette program er klassificeret som <xliff:g id="RATING">%1$s</xliff:g>. Du skal indtaste din pinkode for at se programmet"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Dette program er ikke klassificeret. Indtast din pinkode for at se programmet"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Angiv din pinkode"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Angiv en pinkode for at aktivere børnesikring"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Angiv ny pinkode"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Pinkoden var forkert. Prøv igen."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Prøv igen. Pinkoden var forkert"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Angiv dit postnummer."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Appen Tv-kanaler bruger postnummeret til at levere en komplet tv-guide til tv-kanalerne."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Angiv dit postnummer"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Ugyldigt postnummer"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Indstillinger"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Tilpas kanallisten"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Vælg kanaler til din programoversigt"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanalkilder"</string>
-    <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Der er nye tilgængelige kanaler"</string>
+    <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nye tilgængelige kanaler"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Børnesikring"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Optag en direkte udsendelse, mens du ser den, så du kan sætte den på pause eller spole tilbage i den.\nAdvarsel! Denne intensive brug af den interne lagerplads kan reducere lagerpladsens levetid."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Open source-licenser"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Open source-licenser"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Send feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Version"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Se denne kanal ved at trykke på højreknappen og angive din pinkode"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Se dette program ved at trykke på højreknappen og angive din pinkode"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Dette program er ikke klassificeret.\nDu kan se programmet ved at trykke på højreknappen og indtaste din pinkode"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Dette program er klassificereret som <xliff:g id="RATING">%1$s</xliff:g>.\nSe dette program ved at trykke på højreknappen og angive din pinkode"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Se denne kanal ved hjælp af standardappen til direkte tv."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Se dette program ved hjælp af standardappen til direkte tv."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Dette program er ikke klassificeret.\nDu kan se programmet ved at bruge standardappen til direkte tv."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Dette program er klassificeret som <xliff:g id="RATING">%1$s</xliff:g>.\nSe dette program ved hjælp af standardappen til direkte tv."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programmet er blokeret"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Dette program er ikke klassificeret"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Dette program er klassificereret som <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Kun lyd"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Svagt signal"</string>
@@ -168,11 +161,11 @@
       <item quantity="other">%1$d kanaler</item>
     </plurals>
     <string name="setup_input_no_channels" msgid="1669327912393163331">"Der er ingen tilgængelige kanaler"</string>
-    <string name="setup_input_new" msgid="3337725672277046798">"Nye"</string>
+    <string name="setup_input_new" msgid="3337725672277046798">"Ny"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Ikke konfigureret"</string>
     <string name="setup_store_action_title" msgid="4083402039720973414">"Få flere kilder"</string>
-    <string name="setup_store_action_description" msgid="6820482635042445297">"Gennemse apps, der viser tv-kanaler"</string>
-    <string name="new_sources_title" msgid="3878933676500061895">"Der er nye tilgængelige kanalkilder"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Find apps med tv-kanaler"</string>
+    <string name="new_sources_title" msgid="3878933676500061895">"Nye tilgængelige kanalkilder"</string>
     <string name="new_sources_description" msgid="749649005588426813">"Du kan få kanaler fra nye kanalkilder.\nKonfigurer dem nu, eller gør det senere i indstillingen for kanalkilder."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Konfigurer nu"</string>
     <string name="new_sources_action_skip" msgid="2501296961258184330">"OK, det er forstået"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Tryk på VÆLG"</b>" for at få adgang til TV-menuen."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Der blev ikke fundet noget tv-input"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Tv-inputtet blev ikke fundet"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP understøttes ikke"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Der er intet tilgængeligt input, som kan vises med PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tunertypen er uegnet. Åbn appen Tv-kanaler for at få tv-input fra tunertypen."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Tuningen mislykkedes"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Der blev ikke fundet nogen app, der kan håndtere denne handling."</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d planlagt optagelse</item>
       <item quantity="other">%1$d planlagte optagelser</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Annuller optagelse"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Stop optagelse"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Se"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Afspil fra begyndelsen"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Genoptag afspilning"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Når der er for mange programmer at optage på samme tid, er det kun programmer med højere prioritet, der optages."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Gem"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Engangsoptagelser har højest prioritet"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Annuller"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Annuller"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Glem"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stop"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Tidsplan for optagelse"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Dette ene program"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Optag dette program i stedet for"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Annuller denne optagelse"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Se nu"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Slet optagelser…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Kan optages"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Optagelse er planlagt"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Modstridende optagelser"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Optager"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Optagelsen mislykkedes"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Læser programmer for at oprette tidsplaner for optagelse"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Læser programmer"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Læser programmer"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Se de seneste optagelser"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Optagelsen af <xliff:g id="PROGRAMNAME">%1$s</xliff:g> er ikke fuldført."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Optagelserne af <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> og <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> er ikke fuldført."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Optagelserne af <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> og <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> er ikke fuldført."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Optagelsen af <xliff:g id="PROGRAMNAME">%1$s</xliff:g> blev ikke fuldført, da der ikke var nok lagerplads."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Optagelserne af <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> og <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> blev ikke fuldført, da der ikke var nok lagerplads."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Optagelserne af <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> og <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> blev ikke fuldført, da der ikke var nok lagerplads."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR kræver mere lagerplads"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Du kan optage programmer med DVR. Der er dog ikke længere nok lagerplads på din enhed til at DVR kan fungere. Tilslut et eksternt drev på mindst <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB, og følg vejledningen i, hvordan du formaterer det som internt lager."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Du kan optage programmer med DVR. Der er dog ikke længere nok lagerplads på din enhed til at DVR kan fungere. Tilslut et eksternt drev på mindst <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB, og følg vejledningen i, hvordan du formaterer det som internt lager."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Der er ikke nok lagerplads"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Dette program kan ikke optages, fordi der ikke er nok lagerplads. Prøv at slette nogle eksisterende optagelser."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Lager mangler"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Noget af det lager, der bruges af DVR, mangler. Tilslut det eksterne drev, du brugte før, for at genaktivere DVR. Alternativt kan du vælge at glemme lageret, hvis det ikke længere er tilgængeligt."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Vil du glemme lageret?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Du mister alt dit optagede indhold og dine tidsplaner."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Skal optagelsen stoppes?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Det optagede indhold gemmes."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Optagelsen af <xliff:g id="PROGRAMNAME">%1$s</xliff:g> stoppes, fordi den falder sammen med dette program. Det indhold, der er optaget, vil blive gemt."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Optagelsen er planlagt, men der er konflikter"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Optagelsen er startet, men der er konflikter"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> optages."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"En optagelse af dette program er allerede planlagt kl. <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Det er allerede optaget"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Dette program er allerede optaget. Du kan finde det i DVR-samlingen."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Optagelsen er planlagt"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> optagelse af <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> optagelser af <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> optagelse af <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> optages ikke på grund af konflikter.</item>
+      <item quantity="other">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> optagelser af <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> af dem optages ikke på grund af konflikter.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> optagelse af <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> afsnit af denne og andre serier optages ikke på grund af konflikter.</item>
+      <item quantity="other">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> optagelser af <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> afsnit af denne og andre serier optages ikke på grund af konflikter.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> optagelse af <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 afsnit af en anden serie optages ikke på grund af konflikter.</item>
+      <item quantity="other">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> optagelser af <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 afsnit af en anden serie optages ikke på grund af konflikter.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> optagelse af <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> afsnit af andre serier optages ikke på grund af konflikter.</item>
+      <item quantity="other">Der er planlagt <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> optagelser af <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> afsnit af andre serier optages ikke på grund af konflikter.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Det optagede program blev ikke fundet."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Relaterede optagelser"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Ingen programbeskrivelse)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d optagelse</item>
       <item quantity="other">%1$d optagelser</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Vil du stoppe optagelsen af serien?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Optagede afsnit kan findes i DVR-samlingen."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stop"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Der optages ingen afsnit lige nu."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Der er ingen tilgængelige tv-serier.\nDe optages, så snart de er tilgængelige.."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minut)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> i dag"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> i morgen"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Resultat"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Optagede programmer"</string>
 </resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index b4cc6c0..32a1b48 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"Mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"Stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Wiedergabesteuerung"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Letzte Kanäle"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanäle"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV-Optionen"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-Optionen"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Wiedergabesteuerung für diesen Kanal nicht verfügbar"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Abspielen oder pausieren"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Vorspulen"</string>
@@ -35,37 +34,19 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Untertitel"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Anzeigemodus"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"An"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Aus"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-Audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Mehr Kanäle erhalten"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Einstellungen"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Quelle"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Wechseln"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"An"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Aus"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Ton"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Hauptoption"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-Fenster"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Unten rechts"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Oben rechts"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Oben links"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Unten links"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Nebeneinander"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Größe"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Groß"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Klein"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Eingangsquelle"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (Antenne/Kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Keine Programminformationen"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Keine Informationen"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blockierter Kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Unbekannte Sprache"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Unbekannte Sprache"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Untertitel für %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Untertitel"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Aus"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Untertitel anpassen"</string>
-    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Systemübergr. Einst. für Untertitel festlegen"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Systemweite Einstellungen für Untertitel festlegen"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Anzeigemodus"</string>
     <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Multi-Audio"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"Mono"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Gruppieren nach"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Diese Sendung ist blockiert."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Diese Sendung hat keine Altersempfehlung"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Diese Sendung wurde als \"<xliff:g id="RATING">%1$s</xliff:g>\" eingestuft."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Der Eingang unterstützt keine automatische Suche."</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Automatische Suche für \"<xliff:g id="TV_INPUT">%s</xliff:g>\" kann nicht gestartet werden."</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d Kanal hinzugefügt</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Keine Kanäle hinzugefügt"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Jugendschutz"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"An"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Aus"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Andere Länder"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Keiner"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ohne"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Ohne Altersempfehlung"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Sendungen ohne Altersempfehlung blockieren"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ohne"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Hohe Einschränkung"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Mäßige Einschränkung"</string>
@@ -124,40 +107,50 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Zum Ansehen dieses Kanals PIN eingeben"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Zum Ansehen dieses Programms PIN eingeben"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Diese Sendung wurde als \"<xliff:g id="RATING">%1$s</xliff:g>\" eingestuft. Gib deinen PIN ein, um sie anzusehen"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Diese Sendung hat keine Altersempfehlung. Gib deine PIN ein, um sie anzusehen."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PIN eingeben"</string>
-    <string name="pin_enter_create_pin" msgid="3385754356793309946">"Erstellen Sie eine PIN, um den Jugendschutz einzurichten."</string>
+    <string name="pin_enter_create_pin" msgid="3385754356793309946">"Erstelle eine PIN, um den Jugendschutz einzurichten."</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Neue PIN eingeben"</string>
     <string name="pin_enter_again" msgid="2618999754723090427">"PIN bestätigen"</string>
     <string name="pin_enter_old_pin" msgid="4588282612931041919">"Aktuelle PIN eingeben"</string>
     <plurals name="pin_enter_countdown" formatted="false" msgid="3415233538538544309">
-      <item quantity="other">Sie haben die PIN zum fünften Mal falsch eingegeben.\nVersuchen Sie es in <xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> Sekunden noch einmal.</item>
-      <item quantity="one">Sie haben die PIN zum fünften Mal falsch eingegeben.\nVersuchen Sie es in <xliff:g id="REMAINING_SECONDS_0">%1$d</xliff:g> Sekunde noch einmal.</item>
+      <item quantity="other">Du hast die PIN zum fünften Mal falsch eingegeben.\nVersuche es in <xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> Sekunden noch einmal.</item>
+      <item quantity="one">Du hast die PIN zum fünften Mal falsch eingegeben.\nVersuche es in <xliff:g id="REMAINING_SECONDS_0">%1$d</xliff:g> Sekunde noch einmal.</item>
     </plurals>
-    <string name="pin_toast_wrong" msgid="2126295626095048746">"Diese PIN war falsch. Versuchen Sie es erneut."</string>
-    <string name="pin_toast_not_match" msgid="4283624338659521768">"Die PIN stimmt nicht. Bitte versuchen Sie es erneut."</string>
+    <string name="pin_toast_wrong" msgid="2126295626095048746">"Diese PIN war falsch. Versuche es erneut."</string>
+    <string name="pin_toast_not_match" msgid="4283624338659521768">"Die PIN stimmt nicht. Bitte versuche es erneut."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Gib deine Postleitzahl ein."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Die Live TV App verwendet die Postleitzahl, um dir die vollständige Programmübersicht der TV-Sender zur Verfügung zu stellen."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Postleitzahl eingeben"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Ungültige Postleitzahl"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Einstellungen"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Kanalliste anpassen"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Kanäle für Programmübersicht auswählen"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanalquellen"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Neue Kanäle verfügbar"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Jugendschutzeinstellungen"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Zeitversetztes Fernsehen"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Wenn du Programme aufnimmst, während du sie dir live ansiehst, kannst du sie pausieren oder zurückspulen.\nWarnung: Dies führt durch die intensive Speichernutzung möglicherweise zu einer verringerten Lebensdauer des internen Speichers."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Open-Source-Lizenzen"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Open-Source-Lizenzen"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Feedback geben"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Version"</string>
-    <string name="tvview_channel_locked" msgid="6486375335718400728">"Um sich diesen Kanal anzusehen, drücken Sie rechts und geben Sie die PIN ein."</string>
-    <string name="tvview_content_locked" msgid="391823084917017730">"Um sich dieses Programm anzusehen, drücken Sie rechts und geben Sie die PIN ein."</string>
-    <string name="tvview_content_locked_format" msgid="3741874636031338247">"Diese Sendung wurde als \"<xliff:g id="RATING">%1$s</xliff:g>\" eingestuft.\nUm sich diese Sendung anzusehen, drücken Sie rechts und geben Sie Ihre PIN ein."</string>
-    <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Um sich diesen Kanal anzusehen, verwenden Sie die Standard-App für die Liveverfolgung von TV-Sendungen."</string>
-    <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Um sich dieses Programm anzusehen, verwenden Sie die Standard-App für die Liveverfolgung von TV-Sendungen."</string>
-    <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Diese Sendung wurde als \"<xliff:g id="RATING">%1$s</xliff:g>\" eingestuft.\nUm sich diese Sendung anzusehen, verwenden Sie die Standard-App für die Liveverfolgung von TV-Sendungen."</string>
+    <string name="tvview_channel_locked" msgid="6486375335718400728">"Um sich diesen Kanal anzusehen, drücke rechts und gib die PIN ein."</string>
+    <string name="tvview_content_locked" msgid="391823084917017730">"Um sich dieses Programm anzusehen, drücke rechts und gib die PIN ein."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Diese Sendung hat keine Altersempfehlung.\nUm sie anzusehen, drücke rechts und gib deine PIN ein."</string>
+    <string name="tvview_content_locked_format" msgid="3741874636031338247">"Diese Sendung wurde als \"<xliff:g id="RATING">%1$s</xliff:g>\" eingestuft.\nUm sich diese Sendung anzusehen, drücke rechts und gib deine PIN ein."</string>
+    <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Um sich diesen Kanal anzusehen, verwendest du die Standard-App für die Liveverfolgung von TV-Sendungen."</string>
+    <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Um sich dieses Programm anzusehen, verwendest du die Standard-App für die Liveverfolgung von TV-Sendungen."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Diese Sendung hat keine Altersempfehlung.\nUm sie anzusehen, verwende die Standard-App für die Liveverfolgung von TV-Sendungen."</string>
+    <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Diese Sendung wurde als \"<xliff:g id="RATING">%1$s</xliff:g>\" eingestuft.\nUm sich diese Sendung anzusehen, verwendest du die Standard-App für die Liveverfolgung von TV-Sendungen."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Das Programm wurde blockiert."</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Diese Sendung hat keine Altersempfehlung"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Diese Sendung wurde als \"<xliff:g id="RATING">%1$s</xliff:g>\" eingestuft."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Nur Audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Schwaches Signal"</string>
     <string name="tvview_msg_no_internet_connection" msgid="7655994401188888231">"Keine Internetverbindung"</string>
     <plurals name="tvview_msg_input_no_resource" formatted="false" msgid="8581894855153658823">
-      <item quantity="other">Dieser Kanal kann bis <xliff:g id="END_TIME_1">%1$s</xliff:g> nicht wiedergegeben werden, weil andere Kanäle aufgenommen werden. \n\nDrücken Sie rechts, um den Aufnahmeplan anzupassen.</item>
-      <item quantity="one">Dieser Kanal kann bis <xliff:g id="END_TIME_0">%1$s</xliff:g> nicht wiedergegeben werden, weil ein anderer Kanal aufgenommen wird. \n\nDrücken Sie rechts, um den Aufnahmeplan anzupassen.</item>
+      <item quantity="other">Dieser Kanal kann bis <xliff:g id="END_TIME_1">%1$s</xliff:g> nicht wiedergegeben werden, weil andere Kanäle aufgenommen werden. \n\nDrücke rechts, um den Aufnahmeplan anzupassen.</item>
+      <item quantity="one">Dieser Kanal kann bis <xliff:g id="END_TIME_0">%1$s</xliff:g> nicht wiedergegeben werden, weil ein anderer Kanal aufgenommen wird. \n\nDrücke rechts, um den Aufnahmeplan anzupassen.</item>
     </plurals>
     <string name="channel_banner_no_title" msgid="8660301979190693176">"Kein Titel"</string>
     <string name="channel_banner_locked_channel_title" msgid="2006564967318945980">"Kanal blockiert"</string>
@@ -173,25 +166,23 @@
     <string name="setup_store_action_title" msgid="4083402039720973414">"Weitere Quellen suchen"</string>
     <string name="setup_store_action_description" msgid="6820482635042445297">"Nach Apps suchen, die Live-TV anbieten"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"Neue Kanalquellen verfügbar"</string>
-    <string name="new_sources_description" msgid="749649005588426813">"Neue Kanalquellen bieten weitere Kanäle an.\nDiese können Sie entweder jetzt oder später über die Einstellung \"Kanalquellen\" einrichten."</string>
+    <string name="new_sources_description" msgid="749649005588426813">"Neue Kanalquellen bieten weitere Kanäle an.\nDiese kannst du entweder jetzt oder später über die Einstellung \"Kanalquellen\" einrichten."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Jetzt einrichten"</string>
     <string name="new_sources_action_skip" msgid="2501296961258184330">"OK"</string>
     <!-- no translation found for intro_title (251772896916795556) -->
     <skip />
-    <string name="intro_description" msgid="7806473686446937307"><b>"Drücken Sie die Auswahltaste"</b>", um auf das TV-Menü zuzugreifen."</string>
+    <string name="intro_description" msgid="7806473686446937307"><b>"Drücke die Auswahltaste"</b>", um auf das TV-Menü zuzugreifen."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Kein TV-Eingang gefunden"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV-Eingang konnte nicht gefunden werden."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP wird nicht unterstützt."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Es ist kein Eingang für die PIP-Anzeige verfügbar."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tunertyp ungeeignet, bitte Live TV App für TV-Eingang des Tunertyps starten"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Fehler beim Einstellen"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Für diese Aktion wurde keine App gefunden."</string>
-    <string name="msg_all_channels_hidden" msgid="777397634062471936">"Alle Quellkanäle sind ausgeblendet.\nWählen Sie mindestens einen Kanal aus, den Sie anschauen möchten."</string>
+    <string name="msg_all_channels_hidden" msgid="777397634062471936">"Alle Quellkanäle sind ausgeblendet.\nWähle mindestens einen Kanal aus, den du anschauen möchtest."</string>
     <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"Das Video ist unerwarteterweise nicht verfügbar."</string>
-    <string name="msg_back_key_guide" msgid="7404682718828721924">"Die Taste \"Zurück\" gilt für das verbundene Gerät. Zum Beenden drücken Sie auf \"Startseite\"."</string>
+    <string name="msg_back_key_guide" msgid="7404682718828721924">"Die Taste \"Zurück\" gilt für das verbundene Gerät. Zum Beenden drücke auf \"Startseite\"."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Live TV benötigt einen Lesezugriff für die Kanalliste."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Quellen einrichten"</string>
-    <string name="setup_sources_description" msgid="5695518946225445202">"Bei Live-TV wird die Nutzererfahrung mit klassischen Fernsehsendern mit der von Streaming-Kanälen von Apps kombiniert.\n\nRichten Sie zuerst die bereits installierten Kanalquellen ein. Sie können auch im Google Play Store nach weiteren Apps suchen, die Live-TV anbieten."</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"Bei Live-TV wird die Nutzererfahrung mit klassischen Fernsehsendern mit der von Streaming-Kanälen von Apps kombiniert.\n\nRichte zuerst die bereits installierten Kanalquellen ein. Du kannst auch im Google Play Store nach weiteren Apps suchen, die Live-TV anbieten."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Aufnahmen und Zeitpläne"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 Minuten"</string>
     <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 Minuten"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d geplante Aufnahmen</item>
       <item quantity="one">%1$d geplante Aufnahme</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Aufnahme abbrechen"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Aufnahme beenden"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Ansehen"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Von Anfang an abspielen"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Wiedergabe fortsetzen"</string>
@@ -236,7 +229,7 @@
     <string name="dvr_detail_view_schedule" msgid="7137536927421904426">"Aufnahmeplan"</string>
     <string name="dvr_detail_read_more" msgid="2588920758094498544">"Weitere Infos"</string>
     <string name="dvr_series_deletion_title" msgid="7672649492494507574">"Aufnahmen löschen"</string>
-    <string name="dvr_series_deletion_description" msgid="994839237906552969">"Wählen Sie die Folgen aus, die gelöscht werden sollen. Eine Wiederherstellung ist nicht möglich."</string>
+    <string name="dvr_series_deletion_description" msgid="994839237906552969">"Wähle die Folgen aus, die gelöscht werden sollen. Eine Wiederherstellung ist nicht möglich."</string>
     <string name="dvr_series_deletion_no_recordings" msgid="481210819034514">"Es sind keine Aufnahmen zum Löschen vorhanden."</string>
     <string name="dvr_series_select_watched" msgid="3608122404146716502">"Angesehene Folgen auswählen"</string>
     <string name="dvr_series_select_all" msgid="5415749261739544048">"Alle Folgen auswählen"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Wenn zu viele Programme gleichzeitig aufgenommen werden, werden nur die Programme mit höherer Priorität aufgenommen."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Speichern"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Einmalige Aufnahmen haben höchste Priorität"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Abbrechen"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Abbrechen"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Entfernen"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Beenden"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Aufnahmeplan ansehen"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Nur diese Folge"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Stattdessen diese Sendung aufnehmen"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Diesen Aufnahmeplan abbrechen"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Jetzt ansehen"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Aufnahmen löschen…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Kann aufgenommen werden"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Aufnahme geplant"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Konflikt bei der Aufnahme"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Aufnahme"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Aufnahme fehlgeschlagen"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Sendungen werden gelesen, um Aufnahmepläne zu erstellen"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Sendungen werden gelesen"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Sendungen werden gelesen"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Letzte Aufnahmen ansehen"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Die Aufnahme <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ist nicht abgeschlossen."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Die Aufnahmen <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> und <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> sind nicht abgeschlossen."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Die Aufnahmen <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> und <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> sind nicht abgeschlossen."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Die Aufnahme von <xliff:g id="PROGRAMNAME">%1$s</xliff:g> konnte nicht abgeschlossen werden, weil nicht genügend Speicher vorhanden ist."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Die Aufnahmen von <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> und <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> konnten nicht abgeschlossen werden, weil nicht genügend Speicher vorhanden ist."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Die Aufnahmen von <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> und <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> konnten nicht abgeschlossen werden, weil nicht genügend Speicher vorhanden ist."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR benötigt mehr Speicher"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Sie können mit DVR Sendungen aufnehmen, jedoch ist auf Ihrem Gerät momentan nicht ausreichend Speicherplatz vorhanden. Schließen Sie ein externes Laufwerk mit mindestens <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB freiem Speicher an und folgen Sie der Anleitung zur Formatierung als Gerätespeicher."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Du kannst mit DVR Sendungen aufnehmen, jedoch ist auf deinem Gerät momentan nicht ausreichend Speicherplatz vorhanden. Schließ ein externes Laufwerk mit mindestens <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB freiem Speicher an und folge der Anleitung zur Formatierung als Gerätespeicher."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Nicht genug Speicherplatz"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Diese Inhalte werden nicht aufgenommen, weil zu wenig Speicherplatz verfügbar ist. Du kannst Speicherplatz freigeben, indem du ein paar vorhandene Aufnahmen löschst."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Speicher nicht verfügbar"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Ein Teil des DVR-Speichers ist nicht verfügbar. Um DVR neu zu aktivieren, stellen Sie eine Verbindung zu dem externen Gerät her, das Sie zuvor verwendet haben. Sie können den Speicher auch entfernen, wenn er nicht mehr verfügbar ist."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Speicher entfernen?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Alle aufgenommenen Inhalte und Aufnahmepläne gehen verloren."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Aufnahme beenden?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Die aufgenommenen Inhalte werden gespeichert."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Die Aufzeichnung von <xliff:g id="PROGRAMNAME">%1$s</xliff:g> wird aufgrund eines Konflikts mit diesem Programm beendet. Der aufgezeichnete Inhalt wird gespeichert."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Aufnahme geplant, aber es liegen Konflikte vor"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Aufnahme wurde gestartet, aber es liegen Konflikte vor"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> wird aufgenommen."</string>
@@ -300,23 +293,35 @@
       <item quantity="other">Teile von <xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> und %3$d weiteren geplanten Aufnahmen werden nicht aufgenommen.</item>
       <item quantity="one">Teile von <xliff:g id="CONFLICTPROGRAMNAME_1_0">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_1">%2$s</xliff:g> und %4$d weiteren geplanten Aufnahme werden nicht aufgenommen.</item>
     </plurals>
-    <string name="dvr_schedule_dialog_title" msgid="5235629824986156058">"Was möchten Sie aufnehmen?"</string>
-    <string name="dvr_channel_record_duration_dialog_title" msgid="4601361040431047918">"Wie lange möchten Sie aufnehmen?"</string>
+    <string name="dvr_schedule_dialog_title" msgid="5235629824986156058">"Was möchtest du aufnehmen?"</string>
+    <string name="dvr_channel_record_duration_dialog_title" msgid="4601361040431047918">"Wie lange möchtest du aufnehmen?"</string>
     <string name="dvr_already_scheduled_dialog_title" msgid="4525318291210934311">"Schon dem Aufnahmeplan hinzugefügt"</string>
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Diese Sendung wurde dem Aufnahmeplan schon hinzugefügt und wird um <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> aufgenommen."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Schon aufgenommen"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Diese Sendung wurde schon aufgenommen. Sie ist in der DVR-Bibliothek verfügbar."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Serienaufnahme geplant"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> Aufnahmen wurden für <xliff:g id="SERIESNAME_3">%2$s</xliff:g> geplant.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> Aufnahme wurde für <xliff:g id="SERIESNAME_1">%2$s</xliff:g> geplant.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> Aufnahmen wurden für <xliff:g id="SERIESNAME_3">%2$s</xliff:g> geplant. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> davon werden wegen Konflikten nicht aufgezeichnet.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> Aufnahme wurde für <xliff:g id="SERIESNAME_1">%2$s</xliff:g> geplant. Sie wird wegen Konflikten nicht aufgezeichnet.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> Aufnahmen wurden für <xliff:g id="SERIESNAME_4">%2$s</xliff:g> geplant. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> Folgen dieser Serie und anderer Serien werden wegen Konflikten nicht aufgezeichnet.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> Aufnahme wurde für <xliff:g id="SERIESNAME_1">%2$s</xliff:g> geplant. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> Folge dieser oder einer anderen Serie wird wegen Konflikten nicht aufgezeichnet.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> Aufnahmen wurden für <xliff:g id="SERIESNAME_3">%2$s</xliff:g> geplant. 1 Folge einer anderen Serie wird wegen Konflikten nicht aufgezeichnet.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> Aufnahme wurde für <xliff:g id="SERIESNAME_1">%2$s</xliff:g> geplant. 1 Folge einer anderen Serie wird wegen Konflikten nicht aufgezeichnet.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> Aufnahmen wurden für <xliff:g id="SERIESNAME_4">%2$s</xliff:g> geplant. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> Folgen anderer Serien werden wegen Konflikten nicht aufgezeichnet.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> Aufnahme wurde für <xliff:g id="SERIESNAME_1">%2$s</xliff:g> geplant. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> Folge einer anderen Serie wird wegen Konflikten nicht aufgezeichnet.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Aufgenommenes Programm wurde nicht gefunden."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Ähnliche Aufnahmen"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Keine Programmbeschreibung)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d Aufnahmen</item>
       <item quantity="one">%1$d Aufnahme</item>
@@ -333,9 +338,10 @@
     <string name="dvr_series_schedules_settings" msgid="4868501926847903985">"Serieneinstellungen"</string>
     <string name="dvr_series_schedules_start" msgid="8458768834047133835">"Serienaufnahme starten"</string>
     <string name="dvr_series_schedules_stop" msgid="3427479298317584961">"Serienaufnahme beenden"</string>
-    <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Sie möchten die Serienaufnahme beenden?"</string>
+    <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Du möchtest die Serienaufnahme beenden?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Die aufgenommenen Folgen werden in der DVR-Bibliothek gespeichert."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Beenden"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Momentan werden keine Folgen ausgestrahlt."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Keine Folgen verfügbar.\nSie werden aufgenommen, sobald sie verfügbar sind."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d Minuten)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Heute <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Morgen <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Punkte"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Aufgenommene Programme"</string>
 </resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 9e8e042..f996789 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"μονοφων."</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"στερεοφ."</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Στοιχ. ελέγ. αναπαραγωής"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Πρόσφατα κανάλια"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Κανάλια"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Επιλογές TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Επιλογές PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Τα στοιχεία ελέγχου αναπαραγωγής δεν είναι διαθέσιμα γι\' αυτό το κανάλι"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Αναπαραγωγή ή παύση"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Γρήγορη προώθηση"</string>
@@ -35,37 +34,19 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Υπότιτλοι"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Τρόπος εμφάν."</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Ενεργό"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Ανενεργό"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Πολλαπλός ήχος"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Περισσότ. κανάλια"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Ρυθμίσεις"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Πηγή"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Ανταλλαγή"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Ενεργό"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Ανενεργό"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Ήχος"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Κύριο"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Παράθυρο PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Διάταξη"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Κάτω δεξιά"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Επάνω δεξιά"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Επάνω αριστερά"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Κάτω αριστερά"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Δίπλα"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Μέγεθος"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Μεγάλο"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Μικρό"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Πηγή εισόδου"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Τηλεόραση (κεραία/καλωδιακή)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Δεν υπάρχουν πληροφορίες προγράμματος"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Δεν υπάρχουν πληροφορίες"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Αποκλεισμένο κανάλι"</string>
-    <string name="default_language" msgid="4122326459624337928">"Άγνωστη γλώσσα"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Άγνωστη γλώσσα"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Υπότιτλοι %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Υπότιτλοι"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Ανενεργό"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Προσ. μορφοποίησης"</string>
-    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Ορίστε προτ. συστήματος για υπότιτλους"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Προτιμήσεις συστήματος για υπότιτλους"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Τρόπος εμφάν."</string>
     <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Πολλαπλός ήχος"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"μονοφωνικός ήχος"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Ομαδοποίηση κατά"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Αυτό το πρόγραμμα αποκλείστηκε"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Αυτό το πρόγραμμα δεν έχει αξιολόγηση"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Αυτό το πρόγραμμα αξιολογήθηκε ως <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Η είσοδος δεν υποστηρίζει την αυτόματη σάρωση"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Αδύνατη η εκκίνηση της αυτόματης σάρωσης για \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -92,7 +74,6 @@
       <item quantity="one">Προστέθηκε %1$d κανάλι</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Δεν προστέθηκαν κανάλια"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Δέκτης"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Γονικός έλεγχος"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Ενεργό"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Ανενεργό"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Άλλες χώρες"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Κανένα"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Κανένα"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Χωρίς αξιολόγηση"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Αποκλ. προγραμ. χωρίς αξιολόγ."</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Κανένα"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Υψηλοί περιορισμοί"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Μεσαίοι περιορισμοί"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Εισαγάγετε PIN για να δείτε αυτό το κανάλι"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Εισαγάγετε PIN για να δείτε αυτό το πρόγραμμα"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Αυτό το πρόγραμμα αξιολογήθηκε ως <xliff:g id="RATING">%1$s</xliff:g>. Εισαγάγετε το PIN σας για το παρακολουθήσετε"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Αυτό το πρόγραμμα δεν έχει αξιολόγηση. Εισαγάγετε το PIN για να το παρακολουθήσετε"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Εισαγάγετε το PIN σας"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Για να ορίσετε γονικούς ελέγχους, δημιουργήστε ένα PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Εισαγωγή νέου κωδικού PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Λάθος PIN. Δοκιμάστε ξανά."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Δοκιμάστε ξανά, δεν υπάρχει αντιστοιχία PIN"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Εισαγωγή ταχυδρομικού κώδικα"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Η εφαρμογή \"Ζωντανά κανάλια\" θα χρησιμοποιεί τον ταχυδρομικό κώδικα για να παρέχει έναν πλήρη οδηγό προγράμματος για τα τηλεοπτικά κανάλια."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Εισαγωγή ταχυδρομικού κώδικα"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Μη έγκυρος ταχυδρομ. κώδικας"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Ρυθμίσεις"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Προσαρμογή λίστας καναλιών"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Επιλέξτε κανάλια για τον οδηγό προγράμματος"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Πηγές καναλιών"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Νέα διαθέσιμα κανάλια"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Γονικοί έλεγχοι"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Χρονική μετατόπιση"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Κάντε εγγραφή ενώ παρακολουθείτε, για να μπορείτε να κάνετε παύση ή επαναφορά σε ζωντανά προγράμματα.\nΠροειδοποίηση: Αυτή η λειτουργία μπορεί να μειώσει τη χωρητικότητα του εσωτερικού αποθηκευτικού χώρου μέσω της εντατικής χρήσης του."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Άδειες λογισμικού ανοικτού κώδικα"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Άδειες λογισμικού ανοικτού κώδικα"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Αποστολή σχολίων"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Έκδοση"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Για να παρακολουθήσετε αυτό το κανάλι, πατήστε το δεξιά και εισαγάγετε το PIN σας"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Για να παρακολουθήσετε αυτό το πρόγραμμα, πατήστε δεξιά και εισαγάγετε το PIN σας"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Αυτό το πρόγραμμα δεν έχει αξιολόγηση.\nΓια να το παρακολουθήσετε, πατήστε το στοιχείο \"Δεξιά\" και εισαγάγετε το PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Αυτό το πρόγραμμα αξιολογήθηκε ως <xliff:g id="RATING">%1$s</xliff:g>.\nΓια να παρακολουθήσετε αυτό το πρόγραμμα, πατήστε δεξιά και εισαγάγετε το PIN σας"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Για να παρακολουθήσετε αυτό το κανάλι, χρησιμοποιήστε την προεπιλεγμένη εφαρμογή ζωντανής τηλεοπτικής μετάδοσης."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Για να παρακολουθήσετε αυτό το πρόγραμμα, χρησιμοποιήστε την προεπιλεγμένη εφαρμογή ζωντανής τηλεοπτικής μετάδοσης."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Αυτό το πρόγραμμα δεν έχει αξιολόγηση.\nΓια να παρακολουθήσετε αυτό το πρόγραμμα, χρησιμοποιήστε την προεπιλεγμένη εφαρμογή ζωντανής τηλεοπτικής μετάδοσης."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Αυτό το πρόγραμμα χαρακτηρίστηκε <xliff:g id="RATING">%1$s</xliff:g>.\nΓια να παρακολουθήσετε αυτό το πρόγραμμα, χρησιμοποιήστε την προεπιλεγμένη εφαρμογή ζωντανής τηλεοπτικής μετάδοσης."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Το πρόγραμμα αποκλείστηκε"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Αυτό το πρόγραμμα δεν έχει αξιολόγηση"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Αυτό το πρόγραμμα αξιολογήθηκε ως <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Μόνο ήχος"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Ασθενές σήμα"</string>
@@ -171,7 +164,7 @@
     <string name="setup_input_new" msgid="3337725672277046798">"Νέα"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Δεν ρυθμίστηκε"</string>
     <string name="setup_store_action_title" msgid="4083402039720973414">"Λήψη περισσότερων πηγών"</string>
-    <string name="setup_store_action_description" msgid="6820482635042445297">"Περιήγηση σε εφαρμογές που προσφέρουν ζωντανά κανάλια"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Δείτε εφαρμογές με ζωντανά κανάλια"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"Υπάρχουν νέες διαθέσιμες πηγές καναλιών"</string>
     <string name="new_sources_description" msgid="749649005588426813">"Οι νέες πηγές καναλιών προσφέρουν κανάλια.\nΡυθμίστε τες τώρα ή αργότερα μέσω των ρυθμίσεων πηγών καναλιών."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Ρύθμιση τώρα"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Πατήστε το πλήκτρο SELECT"</b>" για να μεταβείτε στο μενού της τηλεόρασης."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Δεν βρέθηκε είσοδος τηλεόρασης"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Δεν είναι δυνατή η εύρεση εισόδου τηλεόρασης"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Το PIP δεν υποστηρίζεται"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Δεν υπάρχει διαθέσιμη είσοδος για εμφάνιση με PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Ακατάλληλος τύπος δέκτη. Εκκινήστε την εφαρμογή Κανάλια ζωντανά για είσοδο τύπου δέκτη τηλεόρασης."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Αποτυχία συντονισμού"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Δεν βρέθηκε εφαρμογή για τη διαχείριση αυτής της ενέργειας."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d προγραμματ. εγγραφές</item>
       <item quantity="one">%1$d προγραμματ. εγγραφή</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Ακύρωση εγγραφής"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Διακοπή εγγραφής"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Παρακολούθηση"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Αναπαραγωγή από την αρχή"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Συνέχ. αναπαραγωγής"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Όταν υπάρχουν πολλά προγράμματα για εγγραφή την ίδια ώρα, θα γίνει εγγραφή μόνο των προγραμμάτων με τις υψηλότερες προτεραιότητες."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Αποθήκευση"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Οι εγγραφές μίας φοράς έχουν την υψηλότερη προτεραιότητα"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Ακύρωση"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Ακύρωση"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Διαγραφή"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Διακοπή"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Προβολή προγραμματισ. εγγραφών"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Αυτό το συγκεκριμένο επεισόδιο"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Αντί αυτού, εγγρ. αυτού του πρ."</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Ακύρωση αυτής της εγγραφής"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Προβολή τώρα"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Διαγραφή εγγραφών…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Με δυνατότητα εγγραφής"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Η εγγραφή προγραμματίστηκε"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Διένεξη εγγραφής"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Εγγραφή"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Αποτυχία εγγραφής"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Γίνεται ανάγνωση προγραμμάτων για δημιουργία προγραμματισμών εγγραφής"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Ανάγνωση προγραμμάτων"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Ανάγνωση προγραμμάτων"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Προβολή πρόσφατων εγγραφών"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Η εγγραφή του προγράμματος <xliff:g id="PROGRAMNAME">%1$s</xliff:g> δεν είναι ολοκληρωμένη."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Οι εγγραφές των προγραμμάτων <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> και <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> δεν είναι ολοκληρωμένες."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Οι εγγραφές των προγραμμάτων <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> και <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> δεν είναι ολοκληρωμένες."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Η εγγραφή του προγράμματος <xliff:g id="PROGRAMNAME">%1$s</xliff:g> δεν ολοκληρώθηκε, λόγω ανεπαρκούς αποθηκευτικού χώρου."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Οι εγγραφές των προγραμμάτων <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> και <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> δεν ολοκληρώθηκαν, λόγω ανεπαρκούς αποθηκευτικού χώρου."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Οι εγγραφές των προγραμμάτων <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> και <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> δεν ολοκληρώθηκαν, λόγω ανεπαρκούς αποθηκευτικού χώρου."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Το DVR χρειάζεται περισσότερο αποθηκευτικό χώρο"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Θα μπορείτε να εγγράψετε προγράμματα με το DVR. Ωστόσο, αυτήν τη στιγμή δεν υπάρχει αρκετός αποθηκευτικός χώρος στη συσκευή σας έτσι ώστε να λειτουργήσει το DVR. Συνδέστε έναν εξωτερικό δίσκο με χωρητικότητα <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB ή μεγαλύτερη και ακολουθήστε τα βήματα για να τον μορφοποιήσετε και να τον ορίσετε ως αποθηκευτικό χώρο της συσκευής."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Θα μπορείτε να εγγράψετε προγράμματα με το DVR. Ωστόσο, αυτήν τη στιγμή δεν υπάρχει αρκετός αποθηκευτικός χώρος στη συσκευή σας έτσι ώστε να λειτουργήσει το DVR. Συνδέστε έναν εξωτερικό δίσκο με χωρητικότητα <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB ή μεγαλύτερη και ακολουθήστε τα βήματα για να τον μορφοποιήσετε και να τον ορίσετε ως αποθηκευτικό χώρο της συσκευής."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Δεν υπάρχει αρκετός αποθηκευτικός χώρος"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Αυτό το πρόγραμμα δεν θα εγγραφεί, επειδή δεν υπάρχει αρκετός αποθηκευτικός χώρος. Δοκιμάστε να διαγράψετε ορισμένες υπάρχουσες εγγραφές."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Ο αποθηκευτικός χώρος λείπει"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Κάποιο τμήμα του αποθηκευτικού χώρου που χρησιμοποιείται από το DVR λείπει. Συνδέστε τον εξωτερικό δίσκο που χρησιμοποιήσατε στο παρελθόν για να ενεργοποιήσετε εκ νέου το DVR. Εναλλακτικά, μπορείτε να επιλέξετε να διαγράψετε τον αποθηκευτικό χώρο αν δεν είναι πλέον διαθέσιμος."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Να διαγραφεί ο αποθηκευτικός χώρος;"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Όλο το εγγεγραμμένο περιεχόμενο και τα χρονοδιαγράμματα θα χαθούν."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Να διακοπεί η εγγραφή;"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Θα γίνει αποθήκευση του περιεχομένου που έχει εγγραφεί."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Η εγγραφή του προγράμματος <xliff:g id="PROGRAMNAME">%1$s</xliff:g> θα τερματιστεί καθώς βρίσκεται σε διένεξη με αυτό το πρόγραμμα. Το περιεχόμενο που έχει εγγραφεί θα αποθηκευτεί."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Η εγγραφή προγραμματίστηκε, αλλά έχει διενέξεις"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Η εγγραφή ξεκίνησε αλλά υπάρχουν διενέξεις"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Θα γίνει εγγραφή του προγράμματος <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Το ίδιο πρόγραμμα έχει προγραμματιστεί για εγγραφή στις <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Έχει ήδη εγγραφεί"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Αυτό το πρόγραμμα έχει ήδη εγγραφεί. Είναι διαθέσιμο στη βιβλιοθήκη DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Η εγγραφή της σειράς προγραμματίστηκε"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> εγγραφές έχουν προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> εγγραφή έχει προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> εγγραφές έχουν προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> από αυτές δεν θα εγγραφούν εξαιτίας διενέξεων.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> εγγραφή έχει προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Δεν θα γίνει η εγγραφή εξαιτίας διενέξεων.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> εγγραφές έχουν προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> επεισόδια αυτής της σειράς και άλλης σειράς δεν θα εγγραφούν εξαιτίας διενέξεων.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> εγγραφή έχει προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> επεισόδια αυτής της σειράς και άλλης σειράς δεν θα εγγραφούν εξαιτίας διενέξεων.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> εγγραφές έχουν προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 επεισόδιο άλλης σειράς δεν θα εγγραφεί εξαιτίας διενέξεων.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> εγγραφή έχει προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 επεισόδιο άλλης σειράς δεν θα εγγραφεί εξαιτίας διενέξεων.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> εγγραφές έχουν προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> επεισόδια άλλης σειράς δεν θα εγγραφούν εξαιτίας διενέξεων.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> εγγραφή έχει προγραμματιστεί για τη σειρά <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> επεισόδια άλλης σειράς δεν θα εγγραφούν εξαιτίας διενέξεων.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Το εγγεγραμμένο πρόγραμμα δεν βρέθηκε."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Σχετικές εγγραφές"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Καμία περιγραφή προγράμματος)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d εγγραφές</item>
       <item quantity="one">%1$d εγγραφή</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Διακοπή εγγραφής σειράς;"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Τα επεισόδια που έχουν εγγραφεί θα εξακολουθήσουν να είναι διαθέσιμα στη βιβλιοθήκη DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Διακοπή"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Δεν προβάλλονται επεισόδια ζωντανά αυτήν τη στιγμή."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Δεν υπάρχουν διαθέσιμα επεισόδια.\nΗ εγγραφή τους θα πραγματοποιηθεί όταν θα είναι διαθέσιμα."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d λεπτά)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> σήμερα"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> αύριο"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Μουσική επένδυση"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Εγγεγραμμένα προγράμματα"</string>
 </resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index bda4e1e..04a53da 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Play controls"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Recent channels"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Channels"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV options"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP options"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Play controls unavailable for this channel"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Play or pause"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Fast-forward"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Closed captions"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Display mode"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"On"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Off"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Get more channels"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Settings"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Source"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Swap"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"On"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Off"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Sound"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Main"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP window"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Bottom right"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Top right"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Top left"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Bottom left"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Side by side"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Size"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Big"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Small"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Input source"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (aerial/cable)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"No programme information"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"No information"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blocked channel"</string>
-    <string name="default_language" msgid="4122326459624337928">"Unknown language"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Unknown language"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Closed captions %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Closed captions"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Off"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Customise formatting"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Group by"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"This programme is blocked"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"This program is unrated"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"The input doesn\'t support auto-scan"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Unable to start auto-scan for \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d channel added</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"No channels added"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Parental controls"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"On"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Off"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Other countries"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"None"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"None"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Unrated"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Block unrated programs"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"None"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"High restrictions"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Medium restrictions"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Enter your PIN to watch this channel"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Enter your PIN to watch this programme"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>. Enter your PIN to watch this programme"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"This program is unrated. Enter your PIN to watch this program"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Enter your PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"To set parental controls, create a PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Enter new PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"That PIN was wrong. Try again."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Try again, PIN doesn\'t match"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Enter your postcode."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Live TV app will use the postcode to provide a complete programme guide for the TV channels."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Enter your postcode"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Invalid postcode"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Settings"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Customise channel list"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Choose channels for your programme guide"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Channel sources"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"New channels available"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Parental controls"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Record while watching so that you can pause or rewind live programmes.\nWarning: This may decrease the life of the internal storage by the intensive use of the storage."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Open-source licences"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Open-source licences"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Send feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Version"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"To watch this channel, press Right and enter your PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"To watch this program, press Right and enter your PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"This program is unrated.\nTo watch this program, press Right and enter your PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>.\nTo watch this programme, press Right and enter your PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"To watch this channel, use the default Live TV app."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"To watch this programme, use the default Live TV app."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"This program is unrated.\nTo watch this program, use the default Live TV app."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>.\nTo watch this programme, use the default Live TV app."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programme is blocked"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"This program is unrated"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audio only"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Weak signal"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Press SELECT"</b>" to access the TV menu."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"No TV input found"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Cannot find the TV input"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP is not supported"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"There is no available input which can be shown with PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tuner type not suitable. Please launch Live TV app for tuner type TV input."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Tune failed"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"No app was found to handle this action."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d recordings scheduled</item>
       <item quantity="one">%1$d recording scheduled</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancel recording"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Stop recording"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Watch"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Play from beginning"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Resume playing"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"When there are too many programmes to be recorded at the same time, only the ones with higher priorities will be recorded."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Save"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"One-time recordings have the highest priority"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancel"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancel"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Forget"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stop"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"View recording schedule"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"This single programme"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Record this one instead"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancel this recording"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Watch now"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Delete recordings…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Recordable"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Recording scheduled"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Recording conflict"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Recording"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Recording failed"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Reading programs to create recording schedules"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Reading programmes"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Reading programmes"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"View recent recordings"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> is incomplete."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> and <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> are incomplete."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> and <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> are incomplete."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> didn\'t complete due to insufficient storage."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> and <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> didn\'t complete due to insufficient storage."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> and <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> didn\'t complete due to insufficient storage."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR needs more storage"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"You will be able to record programmes with DVR. At the moment there is not enough storage on your device for DVR to work. Please connect an external drive that is <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB or larger and follow the steps to format it as device storage."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"You will be able to record programmes with DVR. At the moment there is not enough storage on your device for DVR to work. Please connect an external drive that is <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB or larger and follow the steps to format it as device storage."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Not enough storage"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"This programme will not be recorded because there is not enough storage. Try deleting some existing recordings."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Missing storage"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Some of the storage used by DVR is missing. Please connect the external drive that you used before to re-enable DVR. Alternatively, you can choose to forget the storage if it\'s no longer available."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Forget storage?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"All your recorded content and schedules will be lost."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Stop recording?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"The recorded content will be saved."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> will be stopped because it conflicts with this programme. The recorded content will be saved."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Recording scheduled but has conflicts"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Recording has started but has conflicts"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> will be recorded."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"The same programme has already been scheduled to be recorded at <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Already recorded"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"This programme has already been recorded. It’s available in the DVR library."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Series recording scheduled"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> of them will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. It will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Recorded programme not found."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Related recordings"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(No programme description)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d recordings</item>
       <item quantity="one">%1$d recording</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Stop series recording?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Recorded episodes will remain available in the DVR library."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stop"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"No episodes are on air now."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"No episodes are available.\nThey will be recorded once they are available."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutes)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> today"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> tomorrow"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Score"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Recorded Programmes"</string>
 </resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index bda4e1e..04a53da 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Play controls"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Recent channels"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Channels"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV options"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP options"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Play controls unavailable for this channel"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Play or pause"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Fast-forward"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Closed captions"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Display mode"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"On"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Off"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Get more channels"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Settings"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Source"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Swap"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"On"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Off"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Sound"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Main"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP window"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Bottom right"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Top right"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Top left"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Bottom left"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Side by side"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Size"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Big"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Small"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Input source"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (aerial/cable)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"No programme information"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"No information"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blocked channel"</string>
-    <string name="default_language" msgid="4122326459624337928">"Unknown language"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Unknown language"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Closed captions %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Closed captions"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Off"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Customise formatting"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Group by"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"This programme is blocked"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"This program is unrated"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"The input doesn\'t support auto-scan"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Unable to start auto-scan for \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d channel added</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"No channels added"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Parental controls"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"On"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Off"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Other countries"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"None"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"None"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Unrated"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Block unrated programs"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"None"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"High restrictions"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Medium restrictions"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Enter your PIN to watch this channel"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Enter your PIN to watch this programme"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>. Enter your PIN to watch this programme"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"This program is unrated. Enter your PIN to watch this program"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Enter your PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"To set parental controls, create a PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Enter new PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"That PIN was wrong. Try again."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Try again, PIN doesn\'t match"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Enter your postcode."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Live TV app will use the postcode to provide a complete programme guide for the TV channels."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Enter your postcode"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Invalid postcode"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Settings"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Customise channel list"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Choose channels for your programme guide"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Channel sources"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"New channels available"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Parental controls"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Record while watching so that you can pause or rewind live programmes.\nWarning: This may decrease the life of the internal storage by the intensive use of the storage."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Open-source licences"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Open-source licences"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Send feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Version"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"To watch this channel, press Right and enter your PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"To watch this program, press Right and enter your PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"This program is unrated.\nTo watch this program, press Right and enter your PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>.\nTo watch this programme, press Right and enter your PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"To watch this channel, use the default Live TV app."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"To watch this programme, use the default Live TV app."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"This program is unrated.\nTo watch this program, use the default Live TV app."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>.\nTo watch this programme, use the default Live TV app."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programme is blocked"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"This program is unrated"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audio only"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Weak signal"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Press SELECT"</b>" to access the TV menu."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"No TV input found"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Cannot find the TV input"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP is not supported"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"There is no available input which can be shown with PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tuner type not suitable. Please launch Live TV app for tuner type TV input."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Tune failed"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"No app was found to handle this action."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d recordings scheduled</item>
       <item quantity="one">%1$d recording scheduled</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancel recording"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Stop recording"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Watch"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Play from beginning"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Resume playing"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"When there are too many programmes to be recorded at the same time, only the ones with higher priorities will be recorded."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Save"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"One-time recordings have the highest priority"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancel"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancel"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Forget"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stop"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"View recording schedule"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"This single programme"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Record this one instead"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancel this recording"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Watch now"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Delete recordings…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Recordable"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Recording scheduled"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Recording conflict"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Recording"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Recording failed"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Reading programs to create recording schedules"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Reading programmes"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Reading programmes"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"View recent recordings"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> is incomplete."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> and <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> are incomplete."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> and <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> are incomplete."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> didn\'t complete due to insufficient storage."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> and <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> didn\'t complete due to insufficient storage."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> and <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> didn\'t complete due to insufficient storage."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR needs more storage"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"You will be able to record programmes with DVR. At the moment there is not enough storage on your device for DVR to work. Please connect an external drive that is <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB or larger and follow the steps to format it as device storage."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"You will be able to record programmes with DVR. At the moment there is not enough storage on your device for DVR to work. Please connect an external drive that is <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB or larger and follow the steps to format it as device storage."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Not enough storage"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"This programme will not be recorded because there is not enough storage. Try deleting some existing recordings."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Missing storage"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Some of the storage used by DVR is missing. Please connect the external drive that you used before to re-enable DVR. Alternatively, you can choose to forget the storage if it\'s no longer available."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Forget storage?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"All your recorded content and schedules will be lost."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Stop recording?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"The recorded content will be saved."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> will be stopped because it conflicts with this programme. The recorded content will be saved."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Recording scheduled but has conflicts"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Recording has started but has conflicts"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> will be recorded."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"The same programme has already been scheduled to be recorded at <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Already recorded"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"This programme has already been recorded. It’s available in the DVR library."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Series recording scheduled"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> of them will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. It will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Recorded programme not found."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Related recordings"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(No programme description)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d recordings</item>
       <item quantity="one">%1$d recording</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Stop series recording?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Recorded episodes will remain available in the DVR library."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stop"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"No episodes are on air now."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"No episodes are available.\nThey will be recorded once they are available."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutes)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> today"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> tomorrow"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Score"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Recorded Programmes"</string>
 </resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index bda4e1e..04a53da 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Play controls"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Recent channels"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Channels"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV options"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP options"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Play controls unavailable for this channel"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Play or pause"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Fast-forward"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Closed captions"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Display mode"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"On"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Off"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Get more channels"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Settings"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Source"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Swap"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"On"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Off"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Sound"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Main"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP window"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Bottom right"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Top right"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Top left"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Bottom left"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Side by side"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Size"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Big"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Small"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Input source"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (aerial/cable)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"No programme information"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"No information"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blocked channel"</string>
-    <string name="default_language" msgid="4122326459624337928">"Unknown language"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Unknown language"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Closed captions %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Closed captions"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Off"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Customise formatting"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Group by"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"This programme is blocked"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"This program is unrated"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"The input doesn\'t support auto-scan"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Unable to start auto-scan for \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d channel added</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"No channels added"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Parental controls"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"On"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Off"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Other countries"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"None"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"None"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Unrated"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Block unrated programs"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"None"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"High restrictions"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Medium restrictions"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Enter your PIN to watch this channel"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Enter your PIN to watch this programme"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>. Enter your PIN to watch this programme"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"This program is unrated. Enter your PIN to watch this program"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Enter your PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"To set parental controls, create a PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Enter new PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"That PIN was wrong. Try again."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Try again, PIN doesn\'t match"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Enter your postcode."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Live TV app will use the postcode to provide a complete programme guide for the TV channels."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Enter your postcode"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Invalid postcode"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Settings"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Customise channel list"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Choose channels for your programme guide"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Channel sources"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"New channels available"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Parental controls"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Record while watching so that you can pause or rewind live programmes.\nWarning: This may decrease the life of the internal storage by the intensive use of the storage."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Open-source licences"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Open-source licences"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Send feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Version"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"To watch this channel, press Right and enter your PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"To watch this program, press Right and enter your PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"This program is unrated.\nTo watch this program, press Right and enter your PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>.\nTo watch this programme, press Right and enter your PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"To watch this channel, use the default Live TV app."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"To watch this programme, use the default Live TV app."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"This program is unrated.\nTo watch this program, use the default Live TV app."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>.\nTo watch this programme, use the default Live TV app."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programme is blocked"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"This program is unrated"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"This programme is rated <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audio only"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Weak signal"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Press SELECT"</b>" to access the TV menu."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"No TV input found"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Cannot find the TV input"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP is not supported"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"There is no available input which can be shown with PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tuner type not suitable. Please launch Live TV app for tuner type TV input."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Tune failed"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"No app was found to handle this action."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d recordings scheduled</item>
       <item quantity="one">%1$d recording scheduled</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancel recording"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Stop recording"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Watch"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Play from beginning"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Resume playing"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"When there are too many programmes to be recorded at the same time, only the ones with higher priorities will be recorded."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Save"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"One-time recordings have the highest priority"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancel"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancel"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Forget"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stop"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"View recording schedule"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"This single programme"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Record this one instead"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancel this recording"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Watch now"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Delete recordings…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Recordable"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Recording scheduled"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Recording conflict"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Recording"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Recording failed"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Reading programs to create recording schedules"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Reading programmes"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Reading programmes"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"View recent recordings"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> is incomplete."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> and <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> are incomplete."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> and <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> are incomplete."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> didn\'t complete due to insufficient storage."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> and <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> didn\'t complete due to insufficient storage."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"The recordings of <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> and <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> didn\'t complete due to insufficient storage."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR needs more storage"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"You will be able to record programmes with DVR. At the moment there is not enough storage on your device for DVR to work. Please connect an external drive that is <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB or larger and follow the steps to format it as device storage."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"You will be able to record programmes with DVR. At the moment there is not enough storage on your device for DVR to work. Please connect an external drive that is <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB or larger and follow the steps to format it as device storage."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Not enough storage"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"This programme will not be recorded because there is not enough storage. Try deleting some existing recordings."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Missing storage"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Some of the storage used by DVR is missing. Please connect the external drive that you used before to re-enable DVR. Alternatively, you can choose to forget the storage if it\'s no longer available."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Forget storage?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"All your recorded content and schedules will be lost."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Stop recording?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"The recorded content will be saved."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"The recording of <xliff:g id="PROGRAMNAME">%1$s</xliff:g> will be stopped because it conflicts with this programme. The recorded content will be saved."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Recording scheduled but has conflicts"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Recording has started but has conflicts"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> will be recorded."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"The same programme has already been scheduled to be recorded at <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Already recorded"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"This programme has already been recorded. It’s available in the DVR library."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Series recording scheduled"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> of them will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. It will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> recording has been scheduled for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Recorded programme not found."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Related recordings"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(No programme description)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d recordings</item>
       <item quantity="one">%1$d recording</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Stop series recording?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Recorded episodes will remain available in the DVR library."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stop"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"No episodes are on air now."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"No episodes are available.\nThey will be recorded once they are available."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutes)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> today"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> tomorrow"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Score"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Recorded Programmes"</string>
 </resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 14e9f50..7e1c79d 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"estéreo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Controles de reproducción"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Recientes"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Canales"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opciones de TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opciones de PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Los controles de reproducción no están disponibles en este canal."</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Reproducir o pausar"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avanzar"</string>
@@ -35,37 +34,19 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Subtítulos"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Modo pantalla"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Activada"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Desactivada"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Varios audios"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Obtener canales"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Configuración"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Fuente"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Cambiar"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Activada"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Desactivada"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Sonido"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principal"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Ventana PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Diseño"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Abajo derecha"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Arriba derecha"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Arriba izqda."</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Abajo izquierda"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Lado a lado"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Tamaño"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Grande"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Pequeña"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Fuente de entrada"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Televisión (antena/cable)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"No hay información del programa"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Sin información"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Canal bloqueado"</string>
-    <string name="default_language" msgid="4122326459624337928">"Idioma desconocido"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Idioma desconocido"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtítulos opcionales en %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Subtítulos opcionales"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Desactivado"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personalizar formato"</string>
-    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Preferencias sistema para los subtítulos"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Preferencias del sistema para los subtítulos"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Modo de pantalla"</string>
     <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Varios audios"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"mono"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Agrupar por"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Este programa está bloqueado."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Este programa no está clasificado"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Calificación de este programa: <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"La entrada no admite la búsqueda automática."</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"No se puede iniciar la búsqueda automática de \"<xliff:g id="TV_INPUT">%s</xliff:g>\"."</string>
@@ -92,7 +74,6 @@
       <item quantity="one">Se agregó %1$d canal</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"No se agregaron canales."</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sintonizador"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Control. parentales"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Activado"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Desactivado"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Otros países"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ninguno"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ninguno"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Sin clasificar"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloquear progr. sin clasificar"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ninguno"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restricciones altas"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restricciones medias"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Ingresa tu PIN para ver este canal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Ingresa tu PIN para ver este programa"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Este programa está clasificado como <xliff:g id="RATING">%1$s</xliff:g>. Ingresa tu PIN para mirarlo."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Este programa no está clasificado. Ingresa tu PIN para verlo"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Ingresa tu PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Para configurar controles parentales, debes crear un PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Ingresar nuevo PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"El PIN es incorrecto. Vuelve a intentarlo."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Inténtalo de nuevo, el PIN no coincide."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Ingresa tu código postal"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"La app de Live Channels usará el código postal para brindar la guía completa de programas de los canales de TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Ingresa tu código postal"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Código postal no válido"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Configuración"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalizar lista de canales"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Seleccionar canales de la guía de programas"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Fuentes de canales"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nuevos canales disponibles"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Controles parentales"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Cambio de tiempo"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Graba el contenido mientras lo miras para poder pausar o retroceder los programas en vivo.\nAdvertencia: Es posible que esta función reduzca la vida útil del almacenamiento interno debido a su uso intensivo."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licencias de código abierto"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licencias de código abierto"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Envía comentarios"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versión"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Para mirar este canal, presiona la tecla hacia la derecha e ingresa el PIN."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Para mirar este programa, presiona la tecla hacia la derecha e ingresa el PIN."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Este programa no está clasificado.\nPara verlo, presiona Derecha y, luego, ingresa tu PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Este programa se calificó como <xliff:g id="RATING">%1$s</xliff:g>.\nPara mirarlo, presiona la tecla hacia la derecha e ingresa el PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Para mirar este canal, usa la app de TV en vivo predeterminada."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Para mirar este programa, usa la app de TV en vivo predeterminada."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Este programa no está clasificado.\nPara verlo, usa la app predeterminada de TV en vivo."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Este programa está calificado como <xliff:g id="RATING">%1$s</xliff:g>.\nPara mirarlo, usa la app de TV en vivo predeterminada."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"El programa está bloqueado."</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Este programa no está clasificado"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Calificación de este programa: <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Solo audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Señal débil"</string>
@@ -171,7 +164,7 @@
     <string name="setup_input_new" msgid="3337725672277046798">"Nueva"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Sin configurar"</string>
     <string name="setup_store_action_title" msgid="4083402039720973414">"Obtener más fuentes"</string>
-    <string name="setup_store_action_description" msgid="6820482635042445297">"Explorar apps que ofrecen Canales en vivo"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Ver apps que ofrecen Canales en vivo"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"Nuevas fuentes de canales disponibles"</string>
     <string name="new_sources_description" msgid="749649005588426813">"Nuevas fuentes de canales con canales disponibles.\nPuedes configurarlas ahora o más tarde en la configuración de fuentes de canales."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Configurar ahora"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Presiona SELECCIONAR"</b>" para acceder al menú de la televisión."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"No se encontró ninguna entrada de TV."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"No se puede encontrar la entrada de TV."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"No se admite PIP."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"No hay entradas disponibles que se puedan mostrar con PIP."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tipo de sintonizador no admitido. Abre la aplicación Canales en vivo para el tipo de sintonizador de entrada de TV."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Error al sintonizar"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"No se encontró ninguna aplicación que pueda realizar esta acción."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d grabaciones programadas</item>
       <item quantity="one">%1$d grabación programada</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancelar grabación"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Detener grabación"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Mirar"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Reproducir desde comienzo"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Reanudar reproducción"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Cuando hay demasiados programas para grabar al mismo tiempo, solo se grabarán los que tengan mayor prioridad."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Guardar"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Las grabaciones únicas tienen mayor prioridad"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancelar"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancelar"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Borrar"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Detener"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Ver cronograma de grabación"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Solo este programa"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Grabar este programa en su lugar"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancelar esta grabación"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Mirar ahora"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Borrar grabaciones…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Se puede grabar"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Grabación programada"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Error de grabación"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Grabando"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Se produjo un error al grabar"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Leyendo programas para crear programaciones de grabación"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Leyendo programas"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Leyendo programas"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Ver grabaciones recientes"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"No se completó la grabación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g>"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"No se completó la grabación de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> y <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"No se completó la grabación de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> y <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"No se completó la grabación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> por falta de espacio de almacenamiento."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"No se completó la grabación de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> y <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> por falta de espacio de almacenamiento."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"No se completó la grabación de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> y <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> por falta de espacio de almacenamiento."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"El DVR necesita más espacio de almacenamiento"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Si bien puedes grabar programas con el DVR, no hay espacio de almacenamiento suficiente en tu dispositivo para usar esta opción. Conecta una unidad externa de <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB como mínimo y sigue los pasos para formatearla como almacenamiento del dispositivo."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Si bien puedes grabar programas con el DVR, no hay espacio de almacenamiento suficiente en tu dispositivo para usar esta opción. Conecta una unidad externa de <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB como mínimo y sigue los pasos para formatearla como almacenamiento del dispositivo."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"No hay suficiente espacio de almacenamiento"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"No se grabará este programa porque no hay suficiente espacio de almacenamiento. Intenta borrar algunas grabaciones existentes."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Falta almacenamiento"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Falta parte del almacenamiento que se usa para DVR. Conecta la unidad externa que usaste anteriormente para volver a habilitar esta función. También puedes borrar el almacenamiento si ya no está disponible."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"¿Borrar almacenamiento?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Se perderán todas las programaciones y los contenidos grabados."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"¿Deseas detener la grabación?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Se guardará el contenido grabado."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Se detendrá la grabación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> porque entra en conflicto con este programa. Sin embargo, se guardará el contenido grabado."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Grabación programada con conflictos"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Comenzó la grabación, pero tiene problemas"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Se grabará <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"El mismo programa se grabará a las <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Programa grabado"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Este programa ya está grabado. Está disponible en la biblioteca de DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Se programó la grabación de series"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">Se programaron <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaciones de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">Se programó <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación de <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">Se programaron <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaciones de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. No se grabarán <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> de ellas debido a algunos conflictos.</item>
+      <item quantity="one">Se programó <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación de <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. No podrá completarse debido a algunos conflictos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">Se programaron <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> grabaciones de <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. No se grabarán <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodios de esta serie y de otras debido a algunos conflictos.</item>
+      <item quantity="one">Se programó <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación de <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. No se grabarán <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodios de esta serie y de otras debido a algunos conflictos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">Se programaron <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaciones de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. No se grabará 1 episodio de otra serie debido a algunos conflictos.</item>
+      <item quantity="one">Se programó <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación de <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. No se grabará 1 episodio de otra serie debido a algunos conflictos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">Se programaron <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> grabaciones de <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. No se grabarán <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodios de otra serie debido a algunos conflictos.</item>
+      <item quantity="one">Se programó <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación de <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. No se grabarán <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodios de otra serie debido a algunos conflictos.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"No se encontró el programa grabado."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Grabaciones relacionadas"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Sin descripción del programa)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d grabaciones</item>
       <item quantity="one">%1$d grabación</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"¿Detener grabación de la serie?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Los episodios grabados estarán disponibles en la biblioteca de DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Detener"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"No hay episodios en vivo disponibles en este momento."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"No hay episodios disponibles.\nSe grabarán cuando lo estén."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutos)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Hoy: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Mañana: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Puntuación"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programas grabados"</string>
 </resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index badab6a..b5d00be 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"estéreo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Controles de reproducción"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Canales recientes"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Canales"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opciones de TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opciones de PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Controles de reproducción no disponibles en este canal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Reproducir o pausar"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avance rápido"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Subtítulos"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Modo de pantalla"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Activado"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Desactivado"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Varios audios"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Más canales"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Ajustes"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Fuente"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Cambiar"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Activado"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Desactivado"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Sonido"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principal"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Ventana PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Diseño"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Abajo derecha"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Arriba derecha"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Arriba izquierda"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Abajo izquierda"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"En paralelo"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Dimensiones"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Grande"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Pequeño"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Fuente de entrada"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/cable)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"No hay información del programa"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Sin información"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Canal bloqueado"</string>
-    <string name="default_language" msgid="4122326459624337928">"Idioma desconocido"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Idioma desconocido"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtítulos en %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Subtítulos"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Desactivados"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personalizar formato"</string>
@@ -73,7 +54,7 @@
     <string name="multi_audio_channel_surround_6" msgid="6066304966228963942">"envolvente 5.1"</string>
     <string name="multi_audio_channel_surround_8" msgid="2765140653768694313">"envolvente 7.1"</string>
     <string name="multi_audio_channel_suffix" msgid="4443825738196093772">"%d canales"</string>
-    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"Personalizar lista"</string>
+    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"Personalizar lista de canales"</string>
     <string name="edit_channels_item_select_group" msgid="4953000352257999703">"Seleccionar grupo"</string>
     <string name="edit_channels_item_deselect_group" msgid="5092649099546997807">"Anular selección"</string>
     <string name="edit_channels_item_group_by" msgid="7794571851966798199">"Agrupar por"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Agrupar por"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Este programa está bloqueado"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Este programa no se ha clasificado"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Este programa se ha clasificado como <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"La entrada no admite la búsqueda automática"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"No se puede iniciar la búsqueda automática de <xliff:g id="TV_INPUT">%s</xliff:g>"</string>
@@ -92,8 +74,7 @@
       <item quantity="one">%1$d canal añadido</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"No se han añadido canales"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sintonizador"</string>
-    <string name="menu_parental_controls" msgid="2474294054521345840">"Controles parentales"</string>
+    <string name="menu_parental_controls" msgid="2474294054521345840">"Control parental"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Activados"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Desactivados"</string>
     <string name="option_channels_locked" msgid="5797855082297549907">"Canales bloqueados"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Otros países"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ninguno"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ninguna"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Sin clasificar"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloquear progr. sin clasificar"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ninguna"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restricciones altas"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restricciones medias"</string>
@@ -124,8 +107,9 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Introduce el PIN para ver este canal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Introduce el PIN para ver este programa"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Este programa está clasificado como <xliff:g id="RATING">%1$s</xliff:g>. Introduce el PIN para verlo"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Este programa no se ha clasificado. Introduce tu PIN para verlo"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Introduce el número PIN"</string>
-    <string name="pin_enter_create_pin" msgid="3385754356793309946">"Para establecer controles parentales, debes crear un PIN"</string>
+    <string name="pin_enter_create_pin" msgid="3385754356793309946">"Para establecer control parental, debes crear un PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Introduce el nuevo PIN"</string>
     <string name="pin_enter_again" msgid="2618999754723090427">"Confirma el número PIN"</string>
     <string name="pin_enter_old_pin" msgid="4588282612931041919">"Introduce el número PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Ese PIN era incorrecto. Vuelve a intentarlo."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Vuelve a intentarlo, el PIN no coincide"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Introduce tu código postal"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"La aplicación TV en directo se basa en el código postal para ofrecer una programación completa de los canales de televisión disponibles."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Introduce tu código postal"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"El código postal no es válido"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Ajustes"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalizar lista de canales"</string>
-    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Seleccionar canales de la programación"</string>
+    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Seleccionar canales para la guía de programas"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Fuentes de canales"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nuevos canales disponibles"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Control parental"</string>
-    <string name="settings_menu_licenses" msgid="1257646083838406103">"Licencias de software libre"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licencias software libre"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Cambio de tiempo"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Graba el contenido mientras lo ves para poder pausar o rebobinar los programas en directo.\nAdvertencia: Es posble que esta función reduzca la duración del almacenamiento interno debido a su uso intensivo de este."</string>
+    <string name="settings_menu_licenses" msgid="1257646083838406103">"Licencias de código abierto"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Enviar sugerencias"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versión"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Para ver este canal, pulsa la tecla hacia la derecha e introduce el número PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Para ver este programa, pulsa la tecla hacia la derecha e introduce el número PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Este programa no se ha clasificado.\nPara verlo, pulsa Derecha e introduce tu PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Este programa se ha clasificado como <xliff:g id="RATING">%1$s</xliff:g>.\nPara verlo, pulsa la tecla hacia la derecha e introduce el número PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Para ver este canal, utiliza la aplicación de TV en directo predeterminada."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Para ver este programa, utiliza la aplicación de TV en directo predeterminada."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Este programa no se ha clasificado.\nPara verlo, utiliza la aplicación de TV en directo predeterminada."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Este programa está clasificado como <xliff:g id="RATING">%1$s</xliff:g>.\nPara verlo, utiliza la aplicación de TV en directo predeterminada."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"El programa está bloqueado"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Este programa no se ha clasificado"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Este programa se ha clasificado como <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Solo audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Señal débil"</string>
@@ -171,7 +164,7 @@
     <string name="setup_input_new" msgid="3337725672277046798">"Nuevas"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Sin configurar"</string>
     <string name="setup_store_action_title" msgid="4083402039720973414">"Obtener más fuentes"</string>
-    <string name="setup_store_action_description" msgid="6820482635042445297">"Explorar aplicaciones que ofrecen TV en directo"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Ver aplicaciones de TV en directo"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"Nuevas fuentes de canales disponibles"</string>
     <string name="new_sources_description" msgid="749649005588426813">"Hay canales disponibles en las nuevas fuentes de canales.\nPuedes configurarlos ahora o más tarde en los ajustes correspondientes."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Configurar ahora"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Pulsa SELECCIONAR"</b>" para acceder al menú de la TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"No se han encontrado entradas de TV"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"No se puede encontrar la entrada de TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP no admitido"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"No hay entradas disponibles que se puedan mostrar con PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tipo de sintonizador inadecuado. Abre Canales en directo para seleccionar la entrada de TV del tipo de sintonizador."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Error al sintonizar"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"No se ha encontrado ninguna aplicación que pueda realizar esta acción."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d grabaciones programadas</item>
       <item quantity="one">%1$d grabación programada</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancelar grabación"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Detener grabación"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Ver"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Reproducir desde inicio"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Reanudar reproducción"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Cuando haya demasiados programas que grabar al mismo tiempo, solo se grabarán aquellos con mayor prioridad."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Guardar"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Las grabaciones únicas son las que tienen mayor prioridad"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancelar"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancelar"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Olvidar"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Detener"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Ver programación de grabación"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Este programa"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Grabar esta en su lugar"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancelar esta grabación"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Ver ahora"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Eliminar grabaciones…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Se puede grabar"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Grabación programada"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Problema de grabación"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Grabación"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"No se ha podido grabar"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Leyendo programas para crear programaciones de grabación"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Leyendo programas"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Leyendo programas"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Ver grabaciones recientes"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"La grabación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> está incompleta."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Las grabaciones de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> y <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> están incompletas."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Las grabaciones de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> y <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> están incompletas."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"No se ha completado la grabación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> porque no hay espacio de almacenamiento suficiente."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"No se han completado las grabaciones de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> y <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> porque no hay espacio de almacenamiento suficiente."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"No se han completado las grabaciones de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> y <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> porque no hay espacio de almacenamiento suficiente."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Se necesita más almacenamiento para el DVR"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Puedes grabar programas con el DVR, pero no tienes suficiente espacio de almacenamiento en el dispositivo para que el DVR funcione. Conecta una unidad externa que tenga <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB como mínimo y sigue los pasos para formatearlo como almacenamiento del dispositivo."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Puedes grabar programas con el DVR, pero no tienes suficiente espacio de almacenamiento en el dispositivo para que el DVR funcione. Conecta una unidad externa que tenga <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB como mínimo y sigue los pasos para formatearlo como almacenamiento del dispositivo."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"No hay suficiente espacio de almacenamiento"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Este programa no se grabará porque no hay espacio de almacenamiento suficiente. Borra algunas grabaciones."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"No se puede acceder al almacenamiento"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"No se puede acceder a parte del almacenamiento utilizado por el DVR. Para volver a habilitarlo, conecta la unidad externa que has utilizado anteriormente. También puedes indicar que se olvide el almacenamiento si ya no está disponible."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"¿Olvidar almacenamiento?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Se perderán todo el contenido grabado y las programaciones."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"¿Detener grabación?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"El contenido grabado se guardará."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"La grabación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> se detendrá porque entra en conflicto con este programa. El contenido grabado se guardará."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Grabación programada con conflictos"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"La grabación se ha iniciado, pero tiene conflictos"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Se grabará <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Ya se ha programado la grabación del mismo programa para esta hora: <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Ya se ha grabado"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Este programa ya se ha grabado y está disponible en la colección del DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Grabación de series programada"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">Se han programado <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaciones para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">Se ha programado <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">Se han programado <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaciones para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Episodios que no se grabarán debido a conflictos: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+      <item quantity="one">Se ha programado <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Debido a conflictos, no se grabará.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">Se han programado <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> grabaciones para <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Episodios de esta y otras series que no se grabarán debido a conflictos: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="one">Se ha programado <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Episodios de esta y otras series que no se grabarán debido a conflictos: <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">Se han programado <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaciones para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Debido a conflictos, no se grabará 1 episodio de otra serie.</item>
+      <item quantity="one">Se ha programado <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Debido a conflictos, no se grabará 1 episodio de otra serie.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">Se han programado <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> grabaciones para <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Episodios de otras series que no se grabarán debido a conflictos: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="one">Se ha programado <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Episodios de otras series que no se grabarán debido a conflictos: <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g>.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"No se ha encontrado el programa grabado."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Grabaciones relacionadas"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(No hay ninguna descripción)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d grabaciones</item>
       <item quantity="one">%1$d grabación</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"¿Detener la grabación de series?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Los episodios grabados seguirán estando disponibles en la colección del DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Detener"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"No se está emitiendo ningún episodio."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"No hay episodios disponibles.\nSe grabarán cuando estén disponibles."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutos)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Hoy de <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Mañana de <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Puntuación"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programas grabados"</string>
 </resources>
diff --git a/res/values-et-v23/strings.xml b/res/values-et-rEE-v23/strings.xml
similarity index 100%
rename from res/values-et-v23/strings.xml
rename to res/values-et-rEE-v23/strings.xml
diff --git a/res/values-et/arrays.xml b/res/values-et-rEE/arrays.xml
similarity index 100%
rename from res/values-et/arrays.xml
rename to res/values-et-rEE/arrays.xml
diff --git a/res/values-et/rating_system_strings.xml b/res/values-et-rEE/rating_system_strings.xml
similarity index 100%
rename from res/values-et/rating_system_strings.xml
rename to res/values-et-rEE/rating_system_strings.xml
diff --git a/res/values-et/strings.xml b/res/values-et-rEE/strings.xml
similarity index 78%
rename from res/values-et/strings.xml
rename to res/values-et-rEE/strings.xml
index 83022b8..77596a4 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Esituse juhtnupud"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Viimas. kanalid"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanalid"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV-valikud"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-valikud"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Esituse juhtelemendid ei ole selle kanali puhul saadaval"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Esitamine või peatamine"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Edasikerimine"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Subtiitrid"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Kuvarežiim"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Sees"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Väljas"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multiaudio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Hangi kanaleid"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Seaded"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Allikas"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Vaheta"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Sees"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Väljas"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Heli"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Peamine"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-aken"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Paigutus"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"All paremal"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Ülal paremal"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Ülal vasakul"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"All vasakul"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Kõrvuti"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Suurus"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Suur"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Väike"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Sisendallikas"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenn/kaabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Programmiteavet pole"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Teave puudub"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blokeeritud kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Tundmatu keel"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Tundmatu keel"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtiitrid %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Subtiitrid"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Väljas"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Vormingu kohandamine"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Rühmitamisalus:"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"See programm on blokeeritud"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Seda programmi ei ole hinnatud."</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Selle saate reiting on <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Sisend ei toeta automaatset skannimist"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Sisendi „<xliff:g id="TV_INPUT">%s</xliff:g>” automaatset skannimist ei saa alustada"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">Lisatud on %1$d kanal</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Ühtegi kanalit ei lisatud"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Van. järelevalve"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Sees"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Väljas"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Muud riigid"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Puudub"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Puudub"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Hindamata"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Hindamata progr. blokeerimine"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Puudub"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Suured piirangud"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Keskmised piirangud"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Kanali vaatamiseks sisestage PIN-kood"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Saate vaatamiseks sisestage PIN-kood"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Selle saate reiting on <xliff:g id="RATING">%1$s</xliff:g>. Selle saate vaatamiseks sisestage oma PIN-kood"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Seda programmi ei ole hinnatud. Programmi vaatamiseks sisestage oma PIN-kood."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Sisestage PIN-kood"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Vanemliku järelevalve määramiseks looge PIN-kood"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Sisestage uus PIN-kood"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"See PIN-kood oli vale. Proovige uuesti."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Proovige uuesti, PIN-kood pole õige"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Sisestage sihtnumber."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Rakendus Reaalajakanalid kasutab telekanalitele täieliku saatekava pakkumiseks sihtnumbrit."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Sisestage sihtnumber"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Sobimatu sihtnumber"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Seaded"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Kohanda kanaliloendit"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Kanalite valimine saatekava jaoks"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanali allikad"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Saadaval on uued kanalid"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Vanemlik järelevalve"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Ajanihe"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Salvestage vaatamise ajal, et saaksite otseülekande programme peatada või tagasi kerida.\nHoiatus: see võib vähendada sisemise salvestusruumi kasutusaega, kuna salvestusruumi kasutatakse intensiivselt."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Avatud lähtekoodi litsentsid"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Avatud lähtekoodi litsentsid"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Tagasiside saatmine"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versioon"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Kanali vaatamiseks vajutage paremale ja sisestage PIN-kood"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Saate vaatamiseks vajutage paremale ja sisestage PIN-kood"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Seda programmi ei ole hinnatud.\nSelle programmi vaatamiseks vajutage valikut Paremale ja sisestage oma PIN-kood"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Saate reiting on <xliff:g id="RATING">%1$s</xliff:g>\nSaate vaatamiseks vajutage valikut Paremale ja sisestage PIN-kood."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Selle kanali vaatamiseks kasutage otsesaadete vaikerakendust."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Selle saate vaatamiseks kasutage otsesaadete vaikerakendust."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Seda programmi ei ole hinnatud.\nSelle programmi vaatamiseks kasutage Live TV vaikerakendust."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Selle saate reiting on <xliff:g id="RATING">%1$s</xliff:g>.\nSelle saate vaatamiseks kasutage otsesaadete vaikerakendust."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Saade on blokeeritud"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Seda programmi ei ole hinnatud."</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Selle saate reiting on <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Ainult heli"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Nõrk signaal"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"Teleri menüüle juurdepääsemiseks "<b>"vajutage nuppu SELECT"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"TV-sisendit ei leitud"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV-sisendit ei õnnestu leida"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP-d ei toetata"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Pole ühtegi sisendit, mida saab näidata koos PIP-ga"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Sobimatu tuuneri tüüp. Käivitage tuuneri tüübi TV-sisendi jaoks rakendus Otseülekande kanalid."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Häälestamine ebaõnnestus"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Selle toimingu käsitlemiseks ei leitud ühtegi rakendust."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d salvestust on ajakavas</item>
       <item quantity="one">%1$d salvestus on ajakavas</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Loobu salvestamisest"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Peata salvestamine"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Käekell"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Esita algusest"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Jätka esitust"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Kui samal ajal salvestamiseks on liiga palju programme, salvestatakse ainult prioriteetsed programmid."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Salvesta"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Ühekordsete salvestiste prioriteet on kõige kõrgem"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Tühista"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Tühista"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Unusta"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Peata"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Kuva salvestamise ajakava"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Ainult see saade"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Salvesta hoopis see"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Tühista see salvestus"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Kuva nüüd"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Kustuta salvestised …"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Salvestatav"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Salvestamine on ajastatud"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Konflikt salvestamisel"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Salvestamine"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Salvestamine ebaõnnestus"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Programmide lugemine salvestusajakavade loomiseks"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Programmide lugemine"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Programmide lugemine"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Kuva hiljutised salvestised"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Saate <xliff:g id="PROGRAMNAME">%1$s</xliff:g> salvestamine on pooleli."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Saadete <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ja <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> salvestamine on pooleli."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Saadete <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ja <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> salvestamine on pooleli."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Ebapiisava salvestusruumi tõttu ei viidud saate <xliff:g id="PROGRAMNAME">%1$s</xliff:g> salvestamist lõpule."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Ebapiisava salvestusruumi tõttu ei viidud saadete <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ja <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> salvestamist lõpule."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Ebapiisava salvestusruumi tõttu ei viidud saadete <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ja <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> salvestamist lõpule."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR vajab rohkem salvestusruumi"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Saateid saate salvestada DVR-iga. Praegu pole teie seadmes DVR-i töötamiseks siiski piisavalt salvestusruumi. Ühendage väline ketas, mille maht on vähemalt <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB, ja järgige juhiseid selle vormindamiseks salvestusseadmena."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Saateid saate salvestada DVR-iga. Praegu pole teie seadmes DVR-i töötamiseks siiski piisavalt salvestusruumi. Ühendage väline ketas, mille maht on vähemalt <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB, ja järgige juhiseid selle vormindamiseks salvestusseadmena."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Pole piisavalt mälu"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Programmi ei salvestata, kuna salvestusruumi on liiga vähe. Kustutage mõned olemasolevad salvestised."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Puuduv salvestusruum"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Osa DVR-i kasutatavast salvestusruumist on puudu. DVR-i uuesti lubamiseks ühendage väline ketas, mida varem kasutasite. Teise võimalusena saate salvestusruumi unustada, kui see enam saadaval pole."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Kas unustada salvestusruum?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Kogu teie salvestatud sisu ja ajakavad lähevad kaotsi."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Kas peatada salvestamine?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Salvestatud sisu talletatakse."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Saate <xliff:g id="PROGRAMNAME">%1$s</xliff:g> salvestamine peatatakse, kuna see on selle saatega konfliktis. Salvestatud sisu salvestatakse."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Salvestamine on ajastatud, ent ilmnesid vastuolud"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Salvestamine on alanud, kuid ilmnesid vastuolud"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Saadet <xliff:g id="PROGRAMNAME">%1$s</xliff:g> salvestatakse."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Sama saate salvestus on juba lisatud ajakavva algusega <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Juba salvestatud"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"See saade on juba salvestatud. See on saadaval DVR-i kogus."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Sarja salvestamine lisati ajakavasse"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">Seeria <xliff:g id="SERIESNAME_3">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> salvestist.</item>
+      <item quantity="one">Seeria <xliff:g id="SERIESNAME_1">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> salvestis.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">Seeria <xliff:g id="SERIESNAME_3">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> salvestist. Konfliktide tõttu ei salvestata neist <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+      <item quantity="one">Seeria <xliff:g id="SERIESNAME_1">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> salvestis. Konfliktide tõttu seda ei salvestata.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">Seeria <xliff:g id="SERIESNAME_4">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> salvestist. Konfliktide tõttu ei salvestata selle seeria ja muude seeriate <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> jagu.</item>
+      <item quantity="one">Seeria <xliff:g id="SERIESNAME_1">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> salvestis. Konfliktide tõttu ei salvestata selle seeria ja muude seeriate <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> jagu.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">Seeria <xliff:g id="SERIESNAME_3">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> salvestist. Konfliktide tõttu ei salvestata muu seeria 1 jagu.</item>
+      <item quantity="one">Seeria <xliff:g id="SERIESNAME_1">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> salvestis. Konfliktide tõttu ei salvestata muu seeria 1 jagu.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">Seeria <xliff:g id="SERIESNAME_4">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> salvestist. Konfliktide tõttu ei salvestata muu seeria <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> jagu.</item>
+      <item quantity="one">Seeria <xliff:g id="SERIESNAME_1">%2$s</xliff:g> puhul lisati ajakavasse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> salvestis. Konfliktide tõttu ei salvestata muu seeria <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> jagu.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Salvestatud programmi ei leitud."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Seotud salvestised"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Programmi kirjeldust pole)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d salvestist</item>
       <item quantity="one">%1$d salvestis</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Kas peatada seeria salvestamine?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Salvestatud jaod jäävad saadavale DVR-i kogusse."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Peata"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Ühtegi jagu pole praegu eetris."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Ükski osa pole saadaval.\nNeed salvestatakse siis, kui need kättesaadavaks muutuvad."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutit)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Täna vahemikus <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Homme vahemikus <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Tulemus"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Salvestatud programmid"</string>
 </resources>
diff --git a/res/values-eu-v23/strings.xml b/res/values-eu-rES-v23/strings.xml
similarity index 100%
rename from res/values-eu-v23/strings.xml
rename to res/values-eu-rES-v23/strings.xml
diff --git a/res/values-eu/arrays.xml b/res/values-eu-rES/arrays.xml
similarity index 100%
rename from res/values-eu/arrays.xml
rename to res/values-eu-rES/arrays.xml
diff --git a/res/values-eu/rating_system_strings.xml b/res/values-eu-rES/rating_system_strings.xml
similarity index 100%
rename from res/values-eu/rating_system_strings.xml
rename to res/values-eu-rES/rating_system_strings.xml
diff --git a/res/values-eu/strings.xml b/res/values-eu-rES/strings.xml
similarity index 78%
rename from res/values-eu/strings.xml
rename to res/values-eu-rES/strings.xml
index 19a0043..ca3d61a 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"estereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Erreprodukzioa kontrolatzeko aukerak"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Azken kanalak"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanalak"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Telebistaren aukerak"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Pantaila txikia"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Erreprodukzioa kontrolatzeko aukerak ez daude erabilgarri kanal honetan"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Erreproduzitu edo pausatu"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Aurreratu"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Azpitituluak"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Bistaratzeko modua"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"Pantaila txikia"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Aktibatuta"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Desaktibatuta"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Audio anitza"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Kanal gehiago"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Ezarpenak"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Iturburua"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Aldatu"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Aktibatuta"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Desaktibatuta"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Soinua"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Nagusia"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Pantaila txikia"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Diseinua"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Behean eskuinean"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Goian eskuinean"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Goian ezkerrean"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Behean ezkerrean"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Alboz albo"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Tamaina"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Handia"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Txikia"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Sarrera-iturburua"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Telebista (antena/digitala)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Ez dago telesaioei buruzko informaziorik"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Ez dago informaziorik"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blokeatutako kanala"</string>
-    <string name="default_language" msgid="4122326459624337928">"Hizkuntza ezezaguna"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Hizkuntza ezezaguna"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Azpitituluak - %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Azpitituluak"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Desaktibatuta"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Pertsonalizatu formatua"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"Bereizmen estandarra"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Taldekatzeko irizpidea"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Telesaio hau blokeatuta dago"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Programa honek ez du adin-sailkapenik"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Telesaioa \"<xliff:g id="RATING">%1$s</xliff:g>\" gisa sailkatu da"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Sarrerak ez du automatikoki sintonizatzeko aukera onartzen"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Ezin da hasi \"<xliff:g id="TV_INPUT">%s</xliff:g>\" automatikoki sintonizatzen"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d kanal gehitu da</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Ez da gehitu kanalik"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sintonizadorea"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Gurasoen ezarpenak"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Aktibatuta"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Desaktibatuta"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Beste herrialdeak"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Bat ere ez"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Bat ere ez"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Ez du adin-sailkapenik"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokeatu adin-sailkapenik gabeko programak"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Bat ere ez"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Murrizketa asko"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Erdi-mailako murriztapenak"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Kanal hau ikusi nahi baduzu, idatzi PIN kodea."</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Telesaio hau ikusi nahi baduzu, idatzi PIN kodea."</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Programaren balorazioa: <xliff:g id="RATING">%1$s</xliff:g>. Idatzi PIN kodea programa ikusteko."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Programa honek ez du adin-sailkapenik. Programa ikusteko, idatzi PIN kodea."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Idatzi PIN kodea"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Gurasoen kontrol-aukerak zehazteko, sortu PIN kode bat"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Idatzi PIN kode berria"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN kodea ez da zuzena. Saiatu berriro."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN kodeak ez datoz bat. Saiatu berriro."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Idatzi posta-kodea."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"\"Telebista zuzenean\" aplikazioak posta-kodea erabiliko du telebistako kanalen programen gida osoa eskaintzeko."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Idatzi posta-kodea"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Posta-kodeak ez du balio"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Ezarpenak"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Pertsonalizatu zerrenda"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Aukeratu telesaioen gidako kanalak"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanalen iturburuak"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Kanal berriak daude eskuragarri"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Gurasoen ezarpenak"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Zuzeneko igorpenetan erreprodukzioa kontrolatzeko aukera"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Grabatu ikusten ari zarena, zuzeneko igorpenak unean bertan pausatu edo atzeratu ahal izateko.\nAbisua: hori egiteko memoria asko erabiltzen denez, aukera hau erabiltzeak barneko memoriaren iraupena murritz lezake."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Kode irekiko lizentziak"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Kode irekiko lizentziak"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Bidali iritzia"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Bertsioa"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Kanal hau ikusteko, sakatu Eskuinera tekla eta idatzi PIN kodea."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Telesaio hau ikusteko, sakatu Eskuinera tekla eta idatzi PIN kodea."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Programa honek ez du adin-sailkapenik.\nPrograma hau ikusteko, sakatu Eskuinera tekla eta idatzi PIN kodea."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Telesaioa \"<xliff:g id="RATING">%1$s</xliff:g>\" gisa sailkatu da.\nIkusi ahal izateko, sakatu Eskuinera tekla eta idatzi PIN kodea."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Kanala ikusteko, erabili telebista zuzenean ikusteko aplikazio lehenetsia."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Telesaioa ikusi ahal izateko, erabili telebista zuzenean ikusteko aplikazio lehenetsia."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Programa honek ez du adin-sailkapenik.\nPrograma hau ikusteko, erabili telebista zuzenean ikusteko aplikazio lehenetsia."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Telesaioa <xliff:g id="RATING">%1$s</xliff:g> gisa sailkatu da.\nIkusi ahal izateko, erabili telebista zuzenean ikusteko aplikazio lehenetsia."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Telesaioa blokeatuta dago"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Programa honek ez du adin-sailkapenik"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Telesaioa \"<xliff:g id="RATING">%1$s</xliff:g>\" gisa sailkatu da"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audioa soilik"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Seinale ahula"</string>
@@ -181,15 +174,13 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Telebistaren menua atzitzeko, sakatu HAUTATU"</b></string>
     <string name="msg_no_input" msgid="3897674146985427865">"Ez da telebista-sarrerarik aurkitu"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Ezin da aurkitu telebista-sarrera"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Ez da pantaila txikia erabiltzea onartzen"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Ez dago pantaila txikian erakuts daitekeen sarrerarik"</string>
-    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Sintonizagailua ez da egokia. Abiarazi zuzeneko kanalen aplikazioa sintonizagailua telebistaren sarrera gisa erabiltzeko."</string>
+    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Sintonizagailua ez da egokia. Abiarazi Telebista zuzenean aplikazioa sintonizagailua telebistaren sarrera gisa erabiltzeko."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Ezin izan da sintonizatu"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Ez da aurkitu ekintza gauza dezakeen aplikaziorik."</string>
     <string name="msg_all_channels_hidden" msgid="777397634062471936">"Iturburuko kanal guztiak ezkutuan daude.\nHautatu gutxienez kanal bat ikusteko."</string>
     <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"Bideoa ez dago erabilgarri"</string>
     <string name="msg_back_key_guide" msgid="7404682718828721924">"Atzera tekla konektatutako gailuari dagokio. Irteteko, sakatu Hasiera botoia."</string>
-    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Zuzeneko kanalak aplikazioak baimena behar du telebistako programazioa irakurtzeko."</string>
+    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Telebista zuzenean aplikazioak baimena behar du telebistako programazioa irakurtzeko."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Konfiguratu iturburuak"</string>
     <string name="setup_sources_description" msgid="5695518946225445202">"Telebista zuzenean zerbitzuarekin, aplikazioek zuzenean erreproduzitzen dituzten kanalak ohiko telebistaren moduan ikus ditzakezu. \n\nLehen urratsak emateko, konfiguratu instalatutako kanal-iturburuak. Bestela, arakatu Google Play Store denda zuzeneko kanalak eskaintzen dituzten aplikazio gehiago aurkitzeko."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Grabaketak eta grabaketen programazioa"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d grabaketa antolatuta</item>
       <item quantity="one">%1$d grabaketa antolatuta</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Ez grabatu"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Gelditu grabaketa"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Ikusi"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Erreproduzitu hasieratik"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Berrekin"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Aldi berean programa gehiegi grabatu behar badira, lehentasun handieneko programak bakarrik grabatuko dira."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Gorde"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Grabaketa solteek dute lehentasun handiena"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Utzi"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Utzi"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Ahaztu"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Gelditu"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Ikusi grabaketen agenda"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Programa hau bakarrik"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Grabatu beste hau haren ordez"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Utzi grabaketa hau bertan behera"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Ikusi"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Ezabatu grabaketak…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Graba daiteke"</string>
-    <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Grabatzeko antolatuta"</string>
+    <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Grabatzeko programatuta"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Grabatzeko gatazka"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Grabatzen"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Ezin izan da grabatu"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Programak irakurtzen ari gara grabaketa-ordutegiak sortzeko"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Programazioa irakurtzen"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Programazioa irakurtzen"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Ikusi azken grabaketak"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Ezin izan da osorik grabatu <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Ezin izan dira osorik grabatu <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> eta <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Ezin izan dira osorik grabatu <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> eta <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Ezin izan da osorik grabatu <xliff:g id="PROGRAMNAME">%1$s</xliff:g>, memoria agortu delako."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Ezin izan dira osorik grabatu <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> eta <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, memoria agortu delako."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Ezin izan dira osorik grabatu <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> eta <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>, memoria agortu delako."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Bideo-grabagailu digitalak ez dauka behar adina memoria erabilgarri"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Bideo-grabagailu digitalarekin programak grabatu ahal izango dituzu. Dena dela, une honetan ez daukazu bideo-grabagailua erabili ahal izateko behar adina memoria erabilgarri. Konektatu <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB edo gehiago dituen unitate aldagarri bat eta formatea ezazu gailuaren memoria gisa erabiltzeko."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Bideo-grabagailu digitalarekin programak grabatu ahal izango dituzu. Dena dela, une honetan ez daukazu bideo-grabagailua erabili ahal izateko behar adina memoria erabilgarri. Konektatu <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB edo gehiago dituen unitate aldagarri bat eta formatea ezazu gailuaren memoria gisa erabiltzeko."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Ez dago behar adina toki"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Ezingo dugu grabatu telesaio hau, ez delako behar adina toki geratzen. Ezabatu grabaketa batzuk tokia egiteko."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Memoria-unitatea falta da"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Bideo-grabagailu digitalak erabili duen memoria-unitateren bat falta da. Bideo-grabagailu digitala gaitu ahal izateko, konektatu aurrez erabilitako unitate aldagarria. Memoria-unitate hura eskura ez baduzu, berriz, aukera ezazu unitatea ahazteko aukera."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Memoria-unitate hau ahaztea nahi duzu?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Grabatuta edo programatuta duzun eduki guztia galduko da."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Grabaketa gelditu nahi duzu?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Grabatutako edukia gordeta geratuko da."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> grabatzeari utziko zaio programa honekin gatazkan dagoelako. Gorde egingo da grabatutako edukia."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Grabatzeko programatu da baina gatazkan dago beste grabaketa batzuekin"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Grabatzen hasi da, baina gatazkak ditu"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> grabatuko da."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Programa hau bera grabatzeko programatu duzu dagoeneko (<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>)."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Grabatuta dago dagoeneko"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Programa hau grabatuta daukazu dagoeneko. DVR liburutegian duzu ikusgai."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Telesaila grabatzeko antolatuta dago"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaketa antolatu dira (<xliff:g id="SERIESNAME_3">%2$s</xliff:g>).</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabaketa antolatu da (<xliff:g id="SERIESNAME_1">%2$s</xliff:g>).</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaketa antolatu dira (<xliff:g id="SERIESNAME_3">%2$s</xliff:g>). Haietako <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ezin izango dira grabatu gatazkak daudelako.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabaketa antolatu da (<xliff:g id="SERIESNAME_1">%2$s</xliff:g>). Ezin izango da grabatu gatazkak daudelako.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> grabaketa antolatu dira (<xliff:g id="SERIESNAME_4">%2$s</xliff:g>). Telesail horren eta beste batzuen <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> atal ezin izango dira grabatu gatazkak daudelako.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabaketa antolatu da (<xliff:g id="SERIESNAME_1">%2$s</xliff:g>). Telesail horren eta beste batzuen <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> atal ezin izango dira grabatu gatazkak daudelako.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> grabaketa antolatu dira (<xliff:g id="SERIESNAME_3">%2$s</xliff:g>). Beste telesail baten atal bat ezin izango da grabatu gatazkak daudelako.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabaketa antolatu da (<xliff:g id="SERIESNAME_1">%2$s</xliff:g>). Beste telesail baten atal bat ezin izango da grabatu gatazkak daudelako.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> grabaketa antolatu dira (<xliff:g id="SERIESNAME_4">%2$s</xliff:g>). Beste telesail batzuen <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> atal ezin izango dira grabatu gatazkak daudelako.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> grabaketa antolatu da (<xliff:g id="SERIESNAME_1">%2$s</xliff:g>). Beste telesail batzuen <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> atal ezin izango dira grabatu gatazkak daudelako.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Ez da aurkitu grabatutako programa."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Erlazionatutako grabaketak"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Ez dago programaren azalpenik)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d grabaketa</item>
       <item quantity="one">%1$d grabaketa</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Seriea grabatzeari utzi nahi diozu?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"DVR liburutegian gordeta geratuko dira grabatutako atalak."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Gelditu"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Une honetan ez dira ari atalik igortzen."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Ez dago atalik ikusgai.\nIkusgai ezartzen dituztenean grabatuko ditugu."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutu)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Gaur, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Bihar, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Puntuazioa"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Grabatutako programak"</string>
 </resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index 7dd59c2..752f93e 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"مونو"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"استریو"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"کنترل‌های پخش"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"کانال‌های اخیر"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"کانال‌ها"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"گزینه‌‌ تلویزیون"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"‏گزینه‌های PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"دسترسی به کنترل‌های پخش برای این کانال امکان‌پذیر نیست"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"پخش یا مکث"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"جلو بردن سریع"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"زیرنویس‌ها"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"حالت نمایش"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"تصویر در تصویر"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"روشن"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"خاموش"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"چند صدایی"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"دریافت کانا‌ل‌های بیشتر"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"تنظیمات"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"منبع"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"تعویض"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"روشن"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"خاموش"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"صدا"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"اصلی"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"پنجره تصویردرتصویر"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"طرح‌بندی"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"پایین سمت راست"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"بالا سمت راست"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"بالا سمت چپ"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"پایین سمت چپ"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"پهلو به پهلو"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"اندازه"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"بزرگ"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"کوچک"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"منبع ورودی"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"تلویزیون (آنتنی/کابلی)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"هیچ اطلاعات برنامه‌ای وجود ندارد"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"هیچ اطلاعاتی موجود نیست"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"کانال مسدود شده"</string>
-    <string name="default_language" msgid="4122326459624337928">"زبان نامشخص"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"زبان نامشخص"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"‏زیرنویس %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"زیرنویس"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"خاموش"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"سفارشی کردن قالب‌بندی"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"وضوح استاندارد"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"گروه‌بندی براساس"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"این برنامه مسدود است"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"این برنامه رتبه‌بندی نشده است"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"رتبه‌بندی این برنامه <xliff:g id="RATING">%1$s</xliff:g> است."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ورودی از اسکن خودکار پشتیبانی نمی‌کند"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"اسکن خودکار «<xliff:g id="TV_INPUT">%s</xliff:g>» شروع نمی‌شود"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">‏%1$d کانال اضافه شد</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"هیچ کانالی اضافه نشد"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"تیونر"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"کنترل‌های والدین"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"روشن"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"خاموش"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"کشورهای دیگر"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"هیچ‌‌کدام"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"هیچ‌‌کدام"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"بدون رتبه‌بندی"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"مسدود کردن برنامه‌های رتبه‌بندی‌نشده"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"هیچ‌‌کدام"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"محدودیت‌های زیاد"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"محدودیت‌های متوسط"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"برای تماشای این کانال، پین خودتان را وارد کنید"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"برای تماشای این برنامه، پین خودتان را وارد کنید"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"به این برنامه <xliff:g id="RATING">%1$s</xliff:g> رتبه داده شده است. برای تماشای این برنامه کد پین را وارد کنید"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"این برنامه رتبه‌بندی نشده است. برای تماشای این برنامه باید پین خود را وارد کنید."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"پین خودتان را وارد کنید"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"برای تنظیم کنترل‌های والدین، پین ایجاد کنید"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"پین جدید را وارد کنید"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"این پین اشتباه بود. دوباره امتحان کنید."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"دوباره امتحان کنید، پین منطبق نیست"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"زیپ‌کدتان را وارد کنید."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"برنامه «کانال‌های زنده» از زیپ‌کد جهت ارائه یک راهنمای برنامه کامل برای کانال‌های تلویزیونی استفاده می‌کند."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"زیپ‌کدتان را وارد کنید"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"زیپ‌کد نامعتبر است"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"تنظیمات"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"سفارشی کردن فهرست کانال‌ها"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"کانال‌ها را برای راهنمای برنامه‌تان انتخاب کنید"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"منابع کانال"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"کانال‌های جدید در دسترس است"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"کنترل‌های والدین"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"تایم شیفت"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"درحین تماشا ضبط کنید، به‌این‌ترتیب می‌توانید برنامه‌های زنده را موقتاً متوقف کنید یا به عقب برگردانید.\nاخطار: این قابلیت ممکن است به دلیل استفاده بیش‌ازحد از فضای ذخیره‌سازی، باعث کاهش عمرمفید حافظه داخلی شود."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"مجوزهای منبع آزاد"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"مجوزهای منبع آزاد"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ارسال بازخورد"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"نسخه"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"برای مشاهده این کانال، راست را فشار دهید و پین خودتان را وارد کنید"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"برای مشاهده این برنامه، راست را فشار دهید و پین خودتان را وارد کنید"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"‏این برنامه رتبه‌بندی نشده است.\nبرای تماشای این برنامه، Right (راست) را فشار دهید و پین خود را وارد کنید"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"‏رتبه‌بندی این برنامه <xliff:g id="RATING">%1$s</xliff:g> است.\nبرای تماشای این برنامه، Right (راست) را فشار دهید و پین خودتان را وارد کنید."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"برای تماشای این کانال، از برنامه «پخش مستقیم» پیش‌فرض استفاده کنید."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"برای تماشای این برنامه، از برنامه «پخش مستقیم» پیش‌فرض استفاده کنید."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"این برنامه رتبه‌بندی نشده است.\nبرای تماشای این برنامه، از برنامه «پخش مستقیم» پیش‌فرض استفاده کنید."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"به این برنامه رتبه <xliff:g id="RATING">%1$s</xliff:g> داده شده است.\n برای تماشای این برنامه، از برنامه «پخش مستقیم» استفاده کنید."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"برنامه مسدود شده است"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"این برنامه رتبه‌بندی نشده است"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"رتبه‌بندی این برنامه <xliff:g id="RATING">%1$s</xliff:g> است."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"فقط صدا"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"سیگنال ضعیف است"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"‏برای دسترسی به منوی تلویزیون، "<b>"SELECT (انتخاب) را فشار دهید"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"هیچ ورودی تلویزیون یافت نشد"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"نمی‌توان ورودی تلویزیون پیدا کرد"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"تصویر در تصویر پشتیبانی نمی‌شود."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"ورودی قابل نمایش با تصویر در تصویر، در دسترس نیست."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"نوع تیونر مناسب نیست. لطفاً برنامه‌ «کانال‌های مستقیم» را برای ورودی تلویزیون نوع تیونر، راه‌اندازی کنید."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"تنظیم نشد"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"برنامه‌ای برای انجام این اقدام پیدا نشد."</string>
@@ -226,6 +217,8 @@
       <item quantity="one">‏%1$d ضبط زمان‌بندی‌شده</item>
       <item quantity="other">‏%1$d ضبط زمان‌بندی‌شده</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"لغو ضبط"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"توقف ضبط"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ساعت مچی"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"پخش از اول"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"ازسرگیری پخش"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"اگر برنامه‌های زیادی برای ضبط هم‌زمان وجود داشته باشد، فقط برنامه‌های با بیشترین اولویت ضبط خواهند شد."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"ذخیره"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ضبط‌های تکی بالاترین اولویت را دارند"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"لغو"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"لغو"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"فراموش شود"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"توقف"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"مشاهده زمان‌بندی ضبط"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"فقط همین برنامه"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"درعوض این مورد ضبط شود"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"لغو این ضبط"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"اکنون تماشا کنید"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"درحال حذف موارد ضبط‌شده…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"قابل ضبط"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ضبط برنامه‌ریزی‌شده"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ضبط متناقض با زمان‌بندی"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"درحال ضبط"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ضبط ناموفق بود"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"درحال خواندن برنامه‌ها برای ایجاد زمان‌بندی ضبط"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"درحال خواندن برنامه‌ها"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"درحال خواندن برنامه‌ها"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"مشاهده موارد ضبط‌شده اخیر"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"ضبط <xliff:g id="PROGRAMNAME">%1$s</xliff:g> کامل نشده است."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"ضبط <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> و <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> کامل نشده است."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"ضبط <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>، <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> و <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> کامل نشده است."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"به دلیل حافظه ناکافی، ضبط <xliff:g id="PROGRAMNAME">%1$s</xliff:g> کامل نشد."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"به دلیل حافظه ناکافی، ضبط <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> و<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> کامل نشد."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"به دلیل حافظه ناکافی، ضبط <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>، <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> و <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> کامل نشد."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"‏DVR به فضای بیشتری نیاز دارد"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"‏با DVR می‌توانید برنامه‌ها را ضبط کنید. اما اکنون فضای ذخیره‌سازی کافی در دستگاهتان وجود ندارد و DVR کار نمی‌کند. لطفاً درایو خارجی‌‌ای با حجم <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> گیگابایت یا بیشتر متصل کنید و برای قالب‌بندی آن‌ به‌عنوان حافظه دستگاه این مراحل را دنبال کنید."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"‏با DVR می‌توانید برنامه‌ها را ضبط کنید. اما اکنون فضای ذخیره‌سازی کافی در دستگاهتان وجود ندارد و DVR کار نمی‌کند. لطفاً درایو خارجی‌‌ای با حجم <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> گیگابایت یا بیشتر متصل کنید و برای قالب‌بندی آن‌ به‌عنوان حافظه دستگاه این مراحل را دنبال کنید."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"حافظه ذخیره‌سازی کافی نیست"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"این برنامه ضبط نخوادهد شد، زیرا حافظه ذخیره‌سازی وجود ندارد. برخی از موارد ضبط‌‌شده قبلی را حذف کنید."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"حافظه دردسترس نیست"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"‏مقداری از حافظه‌ای که توسط DVR استفاده می‌شود از بین می‌رود. لطفاً برای فعال‌سازی مجدد DVR، درایو خارجی را که قبلاً‌ استفاده کردید متصل کنید. یا اگر این حافظه دیگر دردسترس نیست می‌توانید انتخاب کنید فراموش شود."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"حافظه فراموش شود؟"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"همه زمان‌بندی‌ها و محتوای ضبط‌شده‌ شما از دست می‌رود."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"ضبط متوقف شود؟"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"محتوای ضبط‌شده ذخیره خواهد شد."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"ضبط <xliff:g id="PROGRAMNAME">%1$s</xliff:g> به دلیل تناقض با این برنامه متوقف خواهد شد. محتوای ضبط‌شده ذخیره می‌شود."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ضبط، زمان‌بندی شده است اما متناقض است"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ضبط شروع شده است اما متناقض است"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ضبط خواهد شد."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"این برنامه قبلاً‌ برای ضبط در <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> زمان‌بندی شده است."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"قبلاً‌ ضبط شده است"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"‏این برنامه قبلاً‌ ضبط شده است و در کتابخانه DVR موجود است."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"ضبط مجموعه زمان‌بندی شد"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_3">%2$s</xliff:g> زمان‌بندی شده است.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_3">%2$s</xliff:g> زمان‌بندی شده است.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_3">%2$s</xliff:g> زمان‌بندی شده است. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> از آن‌ها به دلیل تناقض ضبط نخواهد شد.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_3">%2$s</xliff:g> زمان‌بندی شده است. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> از آن‌ها به دلیل تناقض ضبط نخواهد شد.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_4">%2$s</xliff:g> زمان‌بندی شده است. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> قسمت این مجموعه و مجموعه‌های دیگر به دلیل تناقض ضبط نخواهند شد.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_4">%2$s</xliff:g> زمان‌بندی شده است. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> قسمت این مجموعه و مجموعه‌های دیگر به دلیل تناقض ضبط نخواهند شد.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_3">%2$s</xliff:g> زمان‌بندی شده است. ۱ قسمت مجموعه‌های دیگر به دلیل تناقض ضبط نخواهد شد.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_3">%2$s</xliff:g> زمان‌بندی شده است. ۱ قسمت مجموعه‌های دیگر به دلیل تناقض ضبط نخواهد شد.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_4">%2$s</xliff:g> زمان‌بندی شده است. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> قسمت مجموعه‌های دیگر به دلیل تناقض ضبط نخواهند شد.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ضبط برای <xliff:g id="SERIESNAME_4">%2$s</xliff:g> زمان‌بندی شده است. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> قسمت مجموعه‌های دیگر به دلیل تناقض ضبط نخواهند شد.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"برنامه ضبط‌شده پیدا نشد."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"ضبط‌های مرتبط"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(بدون شرح برنامه)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">‏%1$d ضبط</item>
       <item quantity="other">‏%1$d ضبط</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"ضبط مجموعه متوقف شود؟"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"‏قسمت‌های ضبط‌شده در کتابخانه DVR دردسترس باقی می‌ماند."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"توقف"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"درحال‌حاضر قسمتی پخش مستقیم نمی‌شود."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"هیچ قسمتی موجود نیست.\nهر قسمتی در دسترس قرار بگیرد ضبط خواهد شد."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">‏(%1$d دقیقه)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> امروز"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> فردا"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"امتیاز"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"برنامه‌های ضبط‌شده"</string>
 </resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index b6f5fb7..eba0cc6 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Toistosäätimet"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Viim. kanavat"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanavat"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV-asetukset"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-asetukset"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Toistosäätimet eivät ole käytettävissä tällä kanavalla."</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Toisto tai keskeytys"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Kelaa eteenpäin"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Tekstitykset"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Näyttötila"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Käytössä"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Ei käytössä"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Moniääni"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Lisää kanavia"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Asetukset"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Lähde"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Vaihda"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Käytössä"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Ei käytössä"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Ääni"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Ensisijainen"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-ikkuna"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Asettelu"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Alaoikealla"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Yläoikealla"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Ylävasemmalla"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Alavasemmalla"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Vierekkäin"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Mitat"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Suuri"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Pieni"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Syötteen lähde"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenni/kaapeli)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Ei ohjelmatietoja"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Ei tietoja"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Estetty kanava"</string>
-    <string name="default_language" msgid="4122326459624337928">"Tuntematon kieli"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Tuntematon kieli"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Tekstitykset %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Tekstitykset"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Ei käytössä"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Muokkaa muotoilua"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Ryhmittely:"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Ohjelma on estetty."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ohjelmalla ei ole ikärajaa."</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Tämän ohjelman luokitus on <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Tulo ei tue automaattista skannausta."</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Tulon <xliff:g id="TV_INPUT">%s</xliff:g> automaattista skannausta ei voi käynnistää"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d kanava lisätty</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Kanavia ei lisätty"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Viritin"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Lapsilukko"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Käytössä"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Ei käytössä"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Muut maat"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ei mitään"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ei mitään"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Ei ikärajaa"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Estä ikärajattomat ohjelmat"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ei mitään"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Suuret rajoitukset"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Keskim. rajoitukset"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Anna PIN-koodi, jotta voit katsella tätä kanavaa"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Anna PIN-koodi, jotta voit katsella tätä ohjelmaa"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Tämän ohjelman ikärajoitus on <xliff:g id="RATING">%1$s</xliff:g>. Anna PIN-koodi, jos haluat katsoa tätä ohjelmaa."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Tälle ohjelmalle ei ole määritetty ikärajaa. Anna PIN-koodi, jos haluat katsoa sen."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Anna PIN-koodi"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Aseta lapsilukko luomalla PIN-koodi"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Anna uusi PIN-koodi"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Väärä PIN-koodi. Yritä uudelleen."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN-koodit ovat erilaiset, yritä uudelleen"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Anna postinumero"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Live-kanavat-sovellus tarjoaa postinumeron avulla kaikkien alueellasi näkyvien TV-kanavien ohjelmaoppaan."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Anna postinumero"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Virheellinen postinumero"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Asetukset"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Muokkaa kanavaluetteloa"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Valitse kanavat ohjelmaoppaaseen"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanavalähteet"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Uusia kanavia saatavilla"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Lapsilukko"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Ajansiirto"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Tallentaa katsottavaa ohjelmaa, jolloin lähetettävän ohjelman voi keskeyttää tai sitä voi kelata.\nVaroitus: tämä voi lyhentää sisäisen tallennustilan käyttöikää runsaan käytön vuoksi."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Avoimen lähdekoodin käyttöluvat"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Avoimen lähdekoodin käyttöluvat"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Lähetä palautetta"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versio"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Katsele tätä kanavaa painamalla näppäimellä oikealle ja antamalla PIN-koodi"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Katsele tämä ohjelma painamalla näppäimellä oikealle ja antamalla PIN-koodi"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Tälle ohjelmalle ei ole määritetty ikärajaa.\nPaina oikeaa painiketta ja anna PIN-koodi, jos haluat katsoa sen."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Tämän ohjelman luokitus on <xliff:g id="RATING">%1$s</xliff:g>.\nKatso ohjelma painamalla näppäimellä oikealle ja antamalla PIN-koodi."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Katsele tätä kanavaa TV-lähetyksien oletussovelluksessa."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Katsele tätä ohjelmaa TV-lähetyksien oletussovelluksessa."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Tälle ohjelmalle ei ole määritetty ikärajaa.\nKäytä suoran TV-sisällön oletussovellusta, jos haluat katsoa sen."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Tämän ohjelman ikärajoitus on <xliff:g id="RATING">%1$s</xliff:g>.\nKatsele tätä ohjelmaa TV-lähetyksien oletussovelluksessa."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Ohjelma on estetty"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ohjelmalla ei ole ikärajaa."</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Tämän ohjelman luokitus on <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Vain ääni"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Heikko signaali"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"Avaa TV-valikko "<b>"painamalla VALITSE"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"TV-tuloa ei löytynyt."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV-tuloa ei löydy."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP:tä ei tueta."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Käytettävissä ei ole syötettä, joka voitaisiin näyttää PIP:ssä."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Viritintä ei tueta. Voit käyttää viritintä käynnistämällä Live-kanavat-sovelluksen."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Viritys epäonnistui."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Tätä toimintoa käsittelevää sovellusta ei löydy."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d tallenn. ajastettu</item>
       <item quantity="one">%1$d tallennus ajastettu</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Peruuta tallennus"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Lopeta tallennus"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Katso"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Toista alusta"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Jatka toistoa"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Jos ohjelmia on ajastettu enemmän kuin samalla kertaa voidaan tallentaa, vain tärkeimmät ohjelmat tallennetaan."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Tallenna"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Kertaluotoiset tallennukset ovat tärkeimpiä."</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Peruuta"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Peruuta"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Unohda"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Lopeta"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Näytä tallennusaikataulu"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Vain tämä jakso"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Nauhoita tämä sen sijaan"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Peruuta tämä nauhoitus"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Katso nyt"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Poista tallenteita…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Tallennettavissa"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Tallennus ajastettu"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Tallennusristiriita"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Tallennetaan"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Nauhoitus epäonnistui"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Luetaan ohjelmatietoja tallennusaikataulujen luomista varten."</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Luetaan ohjelmatietoja"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Luetaan ohjelmatietoja"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Näytä uusimmat tallenteet"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Kohdetta <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ei nauhoitettu loppuun."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Kohteita <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ja <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ei nauhoitettu loppuun."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Kohteita <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ja <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ei nauhoitettu loppuun."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Kohdetta <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ei nauhoitettu loppuun, koska tallennustila ei riitä."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Kohteita <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ja <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ei nauhoitettu loppuun, koska tallennustila ei riitä."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Kohteita <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ja <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ei nauhoitettu loppuun, koska tallennustila ei riitä."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR tarvitsee lisää tilaa"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Voit tallentaa ohjelmia DVR:llä. Laitteellasi ei kuitenkaan ole tarpeeksi tilaa DVR:n käyttöön. Yhdistä vähintään <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> Gt:n kokoinen ulkoinen tallennuslaite ja alusta se laitteen tallennustilaksi ohjeiden mukaisesti."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Voit tallentaa ohjelmia DVR:llä. Laitteellasi ei kuitenkaan ole tarpeeksi tilaa DVR:n käyttöön. Yhdistä vähintään <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> Gt:n kokoinen ulkoinen tallennuslaite ja alusta se laitteen tallennustilaksi ohjeiden mukaisesti."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Tallennustila ei riitä"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Tätä ohjelmaa ei tallenneta, koska tallennustila ei riitä. Kokeile poistaa joitakin nykyisiä tallenteita."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Tallennustila puuttuu"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Osa DVR:n käytössä olleesta tallennustilasta puuttuu. Palauta DVR käyttöön liittämällä aiemmin käyttämäsi ulkoinen asema. Voit myös unohtaa tallennustilan, jos asema ei ole enää käytettävissä."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Unohdetaanko tallennustila?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Kaikki tallennettu sisältö ja aikataulut menetetään."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Lopetetaanko tallennus?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Tallennettu sisältö lisätään kirjastoon."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Ohjelman <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nauhoitus pysäytetään, koska se on ristiriidassa tämän ohjelman kanssa. Nauhoitettu sisältö tallennetaan."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Tallennus ajastettu – ristiriitoja havaittu"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Tallennus käynnissä – ristiriitoja havaittu"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> tallennetaan"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Sama ohjelma on jo ajastettu nauhoitettavaksi klo <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Jo nauhoitettu"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Tämä ohjelma on jo nauhoitettu. Se on käytettävissä DVR-kirjastossa."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Sarjan nauhoitus ajastettu"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_3">%2$s</xliff:g> nauhoitusta lisätty.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_1">%2$s</xliff:g> nauhoitus lisätty.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_3">%2$s</xliff:g> nauhoitusta lisätty. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> niistä jätetään nauhoittamatta ristiriidan takia.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_1">%2$s</xliff:g> nauhoitus lisätty. Se jätetään nauhoittamatta ristiriidan takia.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_4">%2$s</xliff:g> nauhoitusta lisätty. Tämän sarjan ja muiden sarjojen <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> jaksoa jätetään nauhoittamatta ristiriidan takia.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_1">%2$s</xliff:g> nauhoitus lisätty. Tämän sarjan ja muiden sarjojen <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> jaksoa jätetään nauhoittamatta ristiriidan takia.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_3">%2$s</xliff:g> nauhoitusta lisätty. Yksi toisen sarjan jakso jätetään nauhoittamatta ristiriidan takia.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_1">%2$s</xliff:g> nauhoitus lisätty. Yksi toisen sarjan jakso jätetään nauhoittamatta ristiriidan takia.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_4">%2$s</xliff:g> nauhoitusta lisätty. Muiden sarjojen <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> jaksoa jätetään nauhoittamatta ristiriidan takia.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> sarjan <xliff:g id="SERIESNAME_1">%2$s</xliff:g> nauhoitus lisätty. Muiden sarjojen <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> jaksoa jätetään nauhoittamatta ristiriidan takia.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Tallennettua ohjelmaa ei löytynyt."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Aiheeseen liittyvät tallenteet"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Ohjelmalla ei ole kuvausta.)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d tallennetta</item>
       <item quantity="one">%1$d tallenne</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Lopetetaanko sarjan tallennus?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Tallennettuja osia voi edelleen katsella DVR:n kirjastossa."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Lopeta"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Jaksoja ei ole tällä hetkellä saatavilla."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Yhtään jaksoa ei ole saatavilla.\nNe nauhoitetaan, kun ne ovat saatavilla."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minuuttia)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> tänään"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> huomenna"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Arvosana"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Tallennetut ohjelmat"</string>
 </resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 1fc794e..80fac2d 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stéréo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Commandes de lecture"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Chaînes récentes"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Chaînes"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Options télé"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Options IDI"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Les commandes de lecture ne sont pas disponibles pour cette chaîne"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Lire ou mettre en pause"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avance rapide"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Sous-titres"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Mode d\'affichage"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"IDI"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Activé"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Désactivé"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Plus de chaînes"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Paramètres"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Source"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Basculer"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Activé"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Désactivé"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Son"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principale"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Fenêtre IDI"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Disposition"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"En bas à droite"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"En haut à droite"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"En haut à gauche"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"En bas à gauche"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Côte à côte"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Taille"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Grande"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Petite"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Source de l\'entrée"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Télévision (antenne/câble)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Aucune information sur le programme"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Pas d\'information"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Chaîne bloquée"</string>
-    <string name="default_language" msgid="4122326459624337928">"Langue : indéterminée"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Langue indéterminée"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Sous-titres en %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Sous-titres"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Désactivé"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personnaliser format"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Grouper par"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Ce programme est bloqué"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ce programme n\'est pas classé"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Ce programme est classé « <xliff:g id="RATING">%1$s</xliff:g> »"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"L\'entrée ne prend pas en charge la recherche automatique"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Impossible de lancer la recherche automatique pour « <xliff:g id="TV_INPUT">%s</xliff:g> »."</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d chaînes ajoutées</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Aucune chaîne ajoutée"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Syntoniseur"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Contrôle parental"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Activer"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Désactivé"</string>
@@ -108,7 +89,9 @@
     <string name="other_countries" msgid="8342216398676184749">"Autres pays"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Aucune"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Aucun"</string>
-    <string name="option_rating_none" msgid="5204552587760414879">"Aucune"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Non classé"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloquer programmes non classés"</string>
+    <string name="option_rating_none" msgid="5204552587760414879">"Aucun"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restrictions élevées"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restrictions moy."</string>
     <string name="option_rating_low" msgid="5800146024503377969">"Restrictions faibles"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Entrez votre NIP pour regarder cette chaîne"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Entrez votre NIP pour regarder ce programme"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Ce programme est classé <xliff:g id="RATING">%1$s</xliff:g>. Entrez votre NIP pour regarder ce programme"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ce programme n\'est pas classé. Entrez votre NIP pour le regarder"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Entrez votre NIP"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Créez un NIP pour régler les contrôles parentaux"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Entrez le nouveau NIP"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Ce NIP est incorrect. Veuillez réessayer."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Le NIP est incorrect. Veuillez réessayer."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Entrez votre code postal."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"L\'application Télé en direct utilisera le code postal pour vous présenter un guide complet des stations de télévision dans votre région."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Entrez votre code postal"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Code postal non valide"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Paramètres"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personnaliser la liste chaînes"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Choisir des chaînes pour le guide des programmes"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Sources des chaînes"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"De nouvelles chaînes sont disponibles"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Contrôles parentaux"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Décalage temporel"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Enregistrez des programmes en direct tout en les regardant afin de pouvoir les mettre en pause ou les rembobiner.\nAvertissement : Cette opération peut réduire la durée de vie de la mémoire de stockage interne en raison de son utilisation intensive."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licences de logiciels libres"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licences de logiciels libres"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Envoyer un commentaire"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Version"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Pour regarder cette chaîne, touchez la droite, puis entrez votre NIP."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Pour regarder ce programme, touchez la droite, puis entrez votre NIP."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ce programme n\'est pas classé.\nPour le regarder, appuyez sur le bouton Droite, puis entrez votre NIP"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Ce programme est classé « <xliff:g id="RATING">%1$s</xliff:g> ». \nPour le regarder, touchez la droite, puis entrez votre NIP."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Pour regarder cette chaîne, utilisez l\'application de télévision en direct par défaut."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Pour regarder ce programme, utilisez l\'application de télévision en direct par défaut."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ce programme n\'est pas classé.\nPour le regarder, utilisez l\'application de télévision en direct par défaut."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Ce programme est classé <xliff:g id="RATING">%1$s</xliff:g>.\nPour le regarder, utilisez l\'application de télévision en direct par défaut."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programme bloqué"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ce programme n\'est pas classé"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Ce programme est classé « <xliff:g id="RATING">%1$s</xliff:g> »"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audio uniquement"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Signal faible"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"Appuyez sur la touche "<b>"Sélectionner"</b>" pour accéder au menu Télévision."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Aucune entrée trouvée"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Entrée introuvable"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Le mode Image dans image n\'est pas pris en charge"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Aucune entrée ne pouvant être affichée en mode IDI"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Le type d\'entrée ne convient pas. Veuillez lancer l\'application Chaînes en direct pour une entrée de type syntoniseur."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Échec des réglages"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Aucune application pouvant gérer cette action n\'a été trouvée."</string>
@@ -190,7 +181,7 @@
     <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"Indisponibilité inattendue de la vidéo"</string>
     <string name="msg_back_key_guide" msgid="7404682718828721924">"La touche RETOUR concerne l\'appareil connecté. Appuyez sur le bouton ACCUEIL pour quitter."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Les chaînes en direct ont besoin de l\'autorisation nécessaire pour lire les programmes télé."</string>
-    <string name="setup_sources_text" msgid="4988039637873759839">"Configurez vos sources"</string>
+    <string name="setup_sources_text" msgid="4988039637873759839">"Configurer vos sources"</string>
     <string name="setup_sources_description" msgid="5695518946225445202">"Avec Télé en direct, diffusez les chaînes proposées par des applications comme s\'il s\'agissait de chaînes de télévision traditionnelles. \n\nCommencez par configurer les sources de chaînes déjà installées. Vous pouvez également parcourir la boutique Google Play Store et rechercher d\'autres applications qui proposent des chaînes en direct."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Enregistrements et horaires"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minutes"</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d enreg. programmé</item>
       <item quantity="other">%1$d enreg. programmés</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Annuler l\'enregistrement"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Arrêter l\'enregistrement"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Regarder"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Lire du début"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Reprendre la lecture"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Quand il y a trop de programmes à enregistrer en même temps, seuls ceux aux priorités les plus élevées sont enregistrés."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Enregistrer"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Les enregistrements ponctuels ont la plus haute priorité"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Annuler"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Annuler"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Supprimer"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Arrêter"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Voir le programme d\'enregistrement"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Uniquement ce programme"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Enregistrez celui-ci à la place"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Annuler cet enregistrement"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Regarder"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Supprimer des enregistrements"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Enregistrable"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Enregistrement programmé"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Conflit d\'enregistrement"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Enregistrement en cours"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Échec de l\'enregistrement"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Lecture des programmes pour créer des horaires d\'enregistrement…"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Lecture des programmes en cours…"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Lecture des programmes en cours…"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Afficher les enregistrements récents"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"L\'enregistrement de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> est incomplet."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Les enregistrements de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> et <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> sont incomplets."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Les enregistrements de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> et <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> sont incomplets."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"L\'enregistrement de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> n\'a pas été terminé à cause d\'un espace de stockage insuffisant."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"L\'enregistrement de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> et <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> n\'a pas été terminé à cause d\'un espace de stockage insuffisant."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"L\'enregistrement de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> et <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> n\'a pas été terminé à cause d\'un espace de stockage insuffisant."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Le magnétoscope numérique a besoin de plus d\'espace"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Vous pourrez enregistrer des programmes avec le magnétoscope numérique. Toutefois, l\'espace de stockage est insuffisant sur votre appareil pour que le magnétoscope numérique puisse fonctionner actuellement. Veuillez brancher un disque externe d\'au moins <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> Go ou suivez les étapes pour le formater en tant qu\'espace de stockage de l\'appareil."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Vous pourrez enregistrer des programmes avec le magnétoscope numérique. Toutefois, l\'espace de stockage est insuffisant sur votre appareil pour que le magnétoscope numérique puisse fonctionner actuellement. Veuillez brancher un disque externe d\'au moins <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> Go ou suivez les étapes pour le formater en tant qu\'espace de stockage de l\'appareil."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Espace de stockage insuffisant"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Ce programme ne sera pas enregistré, car l\'espace de stockage disponible est insuffisant. Essayez de supprimer certains enregistrements."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Espace de stockage manquant"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Une partie de l\'espace de stockage utilisé par le magnétoscope numérique est manquante. Veuillez connecter de nouveau le disque externe que vous avez utilisé auparavant afin de réactiver le magnétoscope numérique. Vous pouvez également supprimer cet espace de stockage s\'il n\'est plus disponible."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Supprimer l\'espace de stockage?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Tous vos contenus enregistrés et vos enregistrements planifiés seront perdus."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Arrêter l\'enregistrement?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Le contenu enregistré sera gardé."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"L\'enregistrement de « <xliff:g id="PROGRAMNAME">%1$s</xliff:g> » sera interrompu, car il crée un conflit avec ce programme. Le contenu enregistré sera conservé."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Enregistrement planifié, mais d\'autres enregistrements sont prévus en même temps."</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"L\'enregistrement a commencé, mais d\'autres enregistrements sont prévus en même temps"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Le programme « <xliff:g id="PROGRAMNAME">%1$s</xliff:g> » sera enregistré."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Vous avez déjà planifié l\'enregistrement de ce programme à <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Déjà enregistré"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Ce programme a déjà été enregistré. Il est accessible dans la bibliothèque du magnétoscope numérique."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"L\'enregistrement de la série est programmé"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. L\'enregistrement (<xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>) ne sera pas effectué en raison de conflits.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> d\'entre eux ne seront pas effectués en raison de conflits.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> épisodes de cette série et d\'une autre série ne seront pas enregistrés en raison de conflits.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> épisodes de cette série et d\'une autre série ne seront pas enregistrés en raison de conflits.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Un épisode d\'une autre série ne sera pas enregistré en raison de conflits.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Un épisode d\'une autre série ne sera pas enregistré en raison de conflits.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> épisodes d\'une autre série ne seront pas enregistrés en raison de conflits.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> épisodes d\'une autre série ne seront pas enregistrés en raison de conflits.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Programme enregistré non trouvé."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Enregistrements connexes"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Programme sans description)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d enregistrement</item>
       <item quantity="other">%1$d enregistrements</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Arrêter l\'enregistrement de la série?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Les épisodes enregistrés resteront accessibles dans la bibliothèque du magnétoscope numérique."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Arrêter"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Aucun épisode n\'est diffusé en ce moment."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Aucun épisode.\nLes épisodes seront enregistrés lorsqu\'ils seront diffusés."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minute)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Aujourd\'hui, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Demain, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Note"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programmes enregistrés"</string>
 </resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index c140aa6..d290b14 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stéréo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Commandes de lecture"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Chaînes récentes"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Chaînes"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Options TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Options PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Commandes de lecture indisponibles pour cette chaîne."</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Lire ou mettre en pause"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avance rapide"</string>
@@ -35,36 +34,18 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Sous-titres"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Mode d\'affichage"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"Mode PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Activé"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Désactivé"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Plus de chaînes"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Paramètres"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Source"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Permuter"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Activé"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Désactivé"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Son"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principale"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Fenêtre mode PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Mise en page"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"En bas à droite"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"En haut à droite"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"En haut à gauche"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"En bas à gauche"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Côte à côte"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Taille"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Grande"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Petite"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Source d\'entrée"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Téléviseur (antenne/câble)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Aucune information sur le programme."</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Aucune information"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Chaîne bloquée"</string>
-    <string name="default_language" msgid="4122326459624337928">"Langue inconnue"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Langue inconnue"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Sous-titres %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Sous-titres"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Désactivé"</string>
-    <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personnaliser le formatage"</string>
+    <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personnaliser le format"</string>
     <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Configurer les paramètres du système pour les sous-titres"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Mode d\'affichage"</string>
     <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Multi-audio"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Grouper par"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Ce programme est bloqué."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ce programme n\'a pas de classification"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Classification de ce programme : <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"L\'entrée n\'est pas compatible avec la recherche automatique."</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Impossible de lancer la recherche automatique pour \"<xliff:g id="TV_INPUT">%s</xliff:g>\"."</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d chaînes ont bien été ajoutées.</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Aucune chaîne ajoutée."</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Contrôle parental"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Activé"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Désactivé"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Autres pays"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Aucune"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Aucun"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Aucune classification"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloquer si sans classification"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Aucun"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restrictions élevées"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restrictions moyennes"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Saisir votre code d\'accès pour regarder cette chaîne"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Saisir votre code d\'accès pour regarder ce programme"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Classification de ce programme : <xliff:g id="RATING">%1$s</xliff:g>. Saisissez votre code pour le regarder."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ce programme n\'a pas de classification. Saisissez votre code pour le regarder."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Saisir votre code d\'accès"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Créer un code d\'accès pour paramétrer le contrôle parental"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Saisir le nouveau code d\'accès"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Ce code d\'accès est incorrect. Veuillez réessayer."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Le code est incorrect. Veuillez réessayer."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Saisissez votre code postal."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"L\'application TV en direct utilise le code postal pour fournir un guide des programmes complet pour les chaînes de télévision."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Saisissez votre code postal"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Code postal incorrect"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Paramètres"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personnaliser liste chaînes"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Choisir des chaînes pour le guide des programmes"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Sources des chaînes"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nouvelles chaînes disponibles"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Contrôle parental"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Contrôle du direct"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Enregistrez des programmes en direct tout en les regardant afin de pouvoir les mettre en pause ou les rembobiner.\nAvertissement : Cette opération peut réduire la durée de vie de la mémoire de stockage interne en raison de son utilisation intensive."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licences Open Source"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licences Open Source"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Envoyer des commentaires"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Version"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Pour regarder cette chaîne, appuyez sur le bouton droit, puis saisissez votre code d\'accès."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Pour regarder ce programme, appuyez sur la droite, puis saisissez votre code d\'accès."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ce programme n\'a pas de classification.\nPour le regarder, appuyez sur la touche droite, puis saisissez votre code."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Classification de ce programme : <xliff:g id="RATING">%1$s</xliff:g>.\nPour le regarder, appuyez sur la touche droite, puis saisissez votre code d\'accès."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Pour regarder cette chaîne, utilisez l\'application de télévision en direct par défaut."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Pour regarder ce programme, utilisez l\'application de télévision en direct par défaut."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ce programme n\'a pas de classification.\nPour le regarder, utilisez l\'application de télévision en direct par défaut."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Classification de ce programme : <xliff:g id="RATING">%1$s</xliff:g>.\nPour regarder ce programme, utilisez l\'application de télévision en direct par défaut."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programme bloqué"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ce programme n\'a pas de classification"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Classification de ce programme : <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audio uniquement"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Signal faible"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Appuyez sur SÉLECTIONNER"</b>" pour accéder au menu de la télévision."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Aucune entrée TV trouvée."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Entrée TV introuvable."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Le mode PIP n\'est pas compatible."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Aucune entrée disponible ne peut être affichée en mode PIP."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Type de tuner non adapté. Veuillez lancer l\'application Chaînes en direct pour l\'entrée TV de type tuner."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Échec des réglages."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Aucune application trouvée pour gérer cette action."</string>
@@ -190,7 +181,7 @@
     <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"Indisponibilité inattendue de la vidéo"</string>
     <string name="msg_back_key_guide" msgid="7404682718828721924">"La touche RETOUR concerne l\'appareil connecté. Appuyez sur le bouton ACCUEIL pour quitter."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"L\'application Chaînes en direct a besoin d\'une autorisation pour accéder au programme TV."</string>
-    <string name="setup_sources_text" msgid="4988039637873759839">"Configurez vos sources."</string>
+    <string name="setup_sources_text" msgid="4988039637873759839">"Configurez vos sources"</string>
     <string name="setup_sources_description" msgid="5695518946225445202">"Avec TV en direct, regardez en streaming les chaînes proposées par des applications comme s\'il s\'agissait de chaînes de télévision traditionnelles. \n\nCommencez par configurer les sources de chaînes déjà installées. Vous pouvez également parcourir le Google Play Store et rechercher d\'autres applications qui proposent des chaînes en direct."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Enregistrements et plannings"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minutes"</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d enregistr. planifié</item>
       <item quantity="other">%1$d enregistr. planifiés</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Annuler l\'enregistrement"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Arrêter enregistrement"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Regarder"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Lire depuis le début"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Reprendre la lecture"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Lorsqu\'il y a trop de programmes à enregistrer simultanément, seuls les programmes aux priorités les plus élevées sont enregistrés."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Enregistrer"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Les enregistrements ponctuels ont la plus haute priorité."</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Annuler"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Annuler"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Supprimer"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Arrêter"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Voir planning d\'enregistrement"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Ce programme uniquement"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Enregistrer ce programme"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Annuler cet enregistrement"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Regarder"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Supprimer des enregistrements"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Enregistrable"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Enregistrement programmé"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Conflit d\'enregistrement"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Enregistrement…"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Échec de l\'enregistrement"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Lecture des programmes pour créer des plannings d\'enregistrement…"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Lecture des programmes…"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Lecture des programmes…"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Afficher les enregistrements récents"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"L\'enregistrement de \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" est incomplet"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Les enregistrements de \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\" et de \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" sont incomplets"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Les enregistrements de \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\", de \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" et de \"<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>\" sont incomplets"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"L\'enregistrement de \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" n\'a pas été effectué en raison d\'un espace de stockage insuffisant."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Les enregistrements de \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\" et de \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" n\'ont pas été effectués en raison d\'un espace de stockage insuffisant."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Les enregistrements de \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\", de \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" et de \"<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>\" n\'ont pas été effectués en raison d\'un espace de stockage insuffisant."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Le magnétoscope numérique a besoin de plus d\'espace"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Vous pourrez enregistrer des programmes avec le magnétoscope numérique. Toutefois, l\'espace de stockage est insuffisant sur votre appareil pour que le magnétoscope numérique puisse fonctionner actuellement. Veuillez brancher un disque externe d\'au moins <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> Go ou suivre les étapes pour le formater en tant qu\'espace de stockage de l\'appareil."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Vous pourrez enregistrer des programmes avec le magnétoscope numérique. Toutefois, l\'espace de stockage est insuffisant sur votre appareil pour que le magnétoscope numérique puisse fonctionner actuellement. Veuillez brancher un disque externe d\'au moins <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> Go ou suivre les étapes pour le formater en tant qu\'espace de stockage de l\'appareil."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Espace de stockage insuffisant"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Ce programme ne sera pas enregistré, car l\'espace de stockage disponible est insuffisant. Essayez de supprimer certains enregistrements."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Espace de stockage manquant"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Une partie de l\'espace de stockage utilisé par le magnétoscope numérique est manquante. Veuillez connecter de nouveau le disque externe que vous avez utilisé auparavant afin de réactiver le magnétoscope numérique. Vous pouvez également supprimer cet espace de stockage s\'il n\'est plus disponible."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Supprimer l\'espace de stockage ?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Tous vos contenus enregistrés et vos enregistrements planifiés seront perdus."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Arrêter l\'enregistrement ?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Le contenu enregistré sera sauvegardé."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"L\'enregistrement de \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" va être interrompu, car il crée un conflit avec ce programme. Le contenu enregistré sera conservé."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Enregistrement planifié, mais d\'autres enregistrements sont prévus en même temps."</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"L\'enregistrement a commencé, mais présente des conflits"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Le programme \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" sera enregistré."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Vous avez déjà planifié l\'enregistrement de ce programme à <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Déjà enregistré"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Ce programme a déjà été enregistré. Il est disponible dans la bibliothèque DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Enregistrement de la série programmé"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. L\'enregistrement (<xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>) ne sera pas effectué en raison de conflits.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> enregistrements ne seront pas effectués en raison de conflits.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> épisodes de cette série et d\'une autre série ne seront pas enregistrés en raison de conflits.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> épisodes de cette série et d\'une autre série ne seront pas enregistrés en raison de conflits.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 épisode d\'une autre série ne sera pas enregistré en raison de conflits.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 épisode d\'une autre série ne sera pas enregistré en raison de conflits.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistrement a été programmé pour <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> épisodes d\'une autre série ne seront pas enregistrés en raison de conflits.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> enregistrements ont été programmés pour <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> épisodes d\'une autre série ne seront pas enregistrés en raison de conflits.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Programme enregistré introuvable."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Enregistrements associés"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Programme sans description)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d enregistrement</item>
       <item quantity="other">%1$d enregistrements</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Arrêter l\'enregistrement de la série ?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Les épisodes enregistrés resteront disponibles dans la bibliothèque DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Arrêter"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Aucun épisode n\'est diffusé actuellement."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Aucun épisode disponible.\nLes épisodes seront enregistrés lorsqu\'ils seront disponibles."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minute)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> aujourd\'hui"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> demain"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Score"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programmes enregistrés"</string>
 </resources>
diff --git a/res/values-gl-v23/strings.xml b/res/values-gl-rES-v23/strings.xml
similarity index 100%
rename from res/values-gl-v23/strings.xml
rename to res/values-gl-rES-v23/strings.xml
diff --git a/res/values-gl/arrays.xml b/res/values-gl-rES/arrays.xml
similarity index 100%
rename from res/values-gl/arrays.xml
rename to res/values-gl-rES/arrays.xml
diff --git a/res/values-gl/rating_system_strings.xml b/res/values-gl-rES/rating_system_strings.xml
similarity index 100%
rename from res/values-gl/rating_system_strings.xml
rename to res/values-gl-rES/rating_system_strings.xml
diff --git a/res/values-gl/strings.xml b/res/values-gl-rES/strings.xml
similarity index 78%
rename from res/values-gl/strings.xml
rename to res/values-gl-rES/strings.xml
index 7ce0ac2..1eea83a 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"estéreo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Controis de reprodución"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Canles recentes"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Canles"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opcións de TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opcións de PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Os controis de reprodución non están dispoñibles nesta canle"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Reprodución ou pausa"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avance rápido"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Subtítulos"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Modo visualiz."</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Activado"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Desactivado"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multiaudio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Obter máis canles"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Configuración"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Fonte"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Cambiar"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Activado"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Desactivado"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Son"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principal"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Ventá de PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Deseño"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Abaixo dereita"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Arriba dereita"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Arriba esquerda"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Abaixo esquerda"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"En paralelo"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Tamaño"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Grande"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Pequeno"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Fonte de entrada"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/cable)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Non hai información do programa"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Non hai información"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Canle bloqueada"</string>
-    <string name="default_language" msgid="4122326459624337928">"Idioma descoñecido"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Idioma descoñecido"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtítulos en %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Subtítulos"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Desactivado"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personalizar formato"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"Definición estándar"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Agrupar por"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Este programa está bloqueado"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Este programa está sen clasificar"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Este programa está clasificado como <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"A entrada non admite a busca automática"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Non é posible iniciar a busca automática para \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -92,7 +74,6 @@
       <item quantity="one">Engadiuse %1$d canle</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Non se engadiron canles"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sintonizador"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Controis parentais"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Activados"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Desactivados"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Outros países"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ningunha"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ningunha"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Sen clasificar"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloquear progr. sen clasificar"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ningún"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restricións altas"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restricións medias"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Introduce o teu PIN para ver esta canle"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Introduce o teu PIN para ver este programa"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Este programa está clasificado como <xliff:g id="RATING">%1$s</xliff:g>. Para velo, introduce o teu PIN"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Este programa está sen clasificar. Para velo, introduce o PIN"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Introduce o teu PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Para definir controis parentais, crea un PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Introduce o novo PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"О PIN era incorrecto. Téntao de novo."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Téntao de novo. O PIN non coincide."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Introduce o teu código postal."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"A aplicación TV en directo usará o teu código postal para ofrecer unha guía de programas completa para as canles da televisión."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Introduce o teu código postal"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"O código postal non é válido"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Configuración"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalizar lista de canles"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Selecciona canles para a túa guía de programas"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Fontes de canles"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Novas canles dispoñibles"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Controis parentais"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Modo en diferido"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Grava o contido mentres o ves para poder pausar ou rebobinar os programas en directo.\nAdvertencia: Con esta acción pode reducirse a duración do almacenamento interno debido ao seu uso intensivo."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licenzas de código aberto"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licenzas de código aberto"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Enviar comentarios"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versión"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Para ver esta canle, preme na tecla cara á dereita e introduce o PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Para ver esta programa, preme na tecla cara á dereita e introduce o PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Este programa está sen clasificar.\nPara velo, preme na tecla cara á dereita e introduce o PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Este programa está clasificado como <xliff:g id="RATING">%1$s</xliff:g>.\nPara ver esta programa, preme na tecla cara á dereita e introduce o PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Para ver esta canle, utiliza a aplicación predeterminada TV en directo."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Para ver este programa, utiliza a aplicación predeterminada TV en directo."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Este programa está sen clasificar.\nPara velo, utiliza a aplicación predeterminada de televisión en directo."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Este programa está clasificado como <xliff:g id="RATING">%1$s</xliff:g>.\nPara velo, utiliza a aplicación predeterminada TV en directo."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"O programa está bloqueado"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Este programa está sen clasificar"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Este programa está clasificado como <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Só audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Sinal feble"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Preme SELECCIONAR"</b>" para acceder ao menú da televisión."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Non se atopou ningunha entrada de televisión"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Non se pode atopar a entrada de televisión"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP non é compatible"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Non hai ningunha entrada que se poida mostrar con PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tipo de sintonizador non adecuado. Inicia a aplicación Canles en directo para a entrada de TV do tipo de sintonizador."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Erro de sintonización"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Non se encontrou ningunha aplicación para procesar esta acción."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d gravacións programadas</item>
       <item quantity="one">%1$d gravación programada</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancelar gravación"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Deter gravación"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Visualizar"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Reproducir desde o inicio"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Retomar reprodución"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Cando hai demasiados programas para gravar á vez, só se gravarán os programas con máis prioridade."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Gardar"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"As gravacións realizadas unha soa vez teñen máis prioridade"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancelar"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancelar"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Borrar"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Deter"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Ver programación de gravación"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Só este programa"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Gravar isto no seu lugar"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancelar esta gravación"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Visualizar agora"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Eliminar gravacións..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Gravable"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Gravación programada"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Conflito de gravación"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Gravando"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Erro na gravación"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Lendo programas para crear programacións de gravacións"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Lendo programas"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Lendo programas"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Ver gravacións recentes"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"A gravación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> non está completa."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"As gravacións de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> e <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> non están completas."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"As gravacións de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> e <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> non están completas."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"A gravación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> non se completou por falta de almacenamento suficiente."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"As gravacións de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> e <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> non se completaron por falta de almacenamento suficiente."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"As gravacións de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> e <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> non se completaron por falta de almacenamento suficiente."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"O DVR precisa máis almacenamento"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Poderás gravar programas con DVR. Non obstante, o teu dispositivo non ten almacenamento suficiente para que funcione DVR. Conecta unha unidade externa de <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB ou máis e sigue os pasos para formatala como almacenamento do dispositivo."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Poderás gravar programas con DVR. Non obstante, o teu dispositivo non ten almacenamento suficiente para que funcione DVR. Conecta unha unidade externa de <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB ou máis e sigue os pasos para formatala como almacenamento do dispositivo."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Non hai almacenamento suficiente"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Este programa non se gravará porque non hai almacenamento suficiente. Proba a eliminar algunhas gravacións."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Falta o almacenamento"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Falta parte do almacenamento que utiliza DVR. Conecta a unidade externa que utilizaches antes para volver activar DVR. Tamén podes decidir borrar o almacenamento se xa non está dispoñible."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Queres borrar o almacenamento?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Perderase toda a programación e o contido gravados."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Queres deter a gravación?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Gardarase o contido gravado."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Deterase a gravación de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> porque supón un conflito con este programa. Gardarase o contido gravado."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Programouse a gravación, pero presenta conflitos"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Iniciouse a gravación pero presenta conflitos"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Gravarase <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Xa se programou a gravación do mesmo programa para a seguinte hora: <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Xa está gravado"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Este programa xa está gravado e está dispoñible na mediateca de DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Programouse a gravación da serie"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">Programáronse <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravacións para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">Programouse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">Programáronse <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravacións para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Non se gravarán <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> delas por causa dun conflito.</item>
+      <item quantity="one">Programouse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Non se gravará por causa dun conflito.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">Programáronse <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> gravacións para <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Non se gravarán <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodios destas series nin doutras por causa dun conflito.</item>
+      <item quantity="one">Programouse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Non se gravarán <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodios destas series nin doutras por causa dun conflito.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">Programáronse <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravacións para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Non se gravará 1 episodio doutras series por causa dun conflito.</item>
+      <item quantity="one">Programouse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Non se gravará 1 episodio doutras series por causa dun conflito.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">Programáronse <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> gravacións para <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Non se gravarán <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodios doutras series por causa dun conflito.</item>
+      <item quantity="one">Programouse <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravación para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Non se gravarán <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episodios doutras series por causa dun conflito.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Non se atopou o programa gravado."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Gravacións relacionadas"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Non hai descrición do programa)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d gravacións</item>
       <item quantity="one">%1$d gravación</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Queres deter a gravación da serie?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Os episodios gravados seguirán dispoñibles na mediateca de DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Deter"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Agora non hai episodios en directo."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Non hai episodios dispoñibles.\nGravaranse unha vez que estean dispoñibles."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutos)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> hoxe"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> mañá"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Puntuación"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programas gravados"</string>
 </resources>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
new file mode 100644
index 0000000..d635088
--- /dev/null
+++ b/res/values-gu-rIN/strings.xml
@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ 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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="audio_channel_mono" msgid="8812941280022167428">"મૉનો"</string>
+    <string name="audio_channel_stereo" msgid="5798223286366598036">"સ્ટીરિઓ"</string>
+    <string name="menu_title_play_controls" msgid="2490237359425190652">"ચલાવવાનાં નિયંત્રણો"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ચૅનલો"</string>
+    <string name="menu_title_options" msgid="7184594626814914022">"TV વિકલ્પો"</string>
+    <string name="play_controls_unavailable" msgid="8900698593131693148">"આ ચૅનલો માટે ચલાવવાનાં નિયંત્રણો ઉપલબ્ધ નથી"</string>
+    <string name="play_controls_description_play_pause" msgid="7225542861669250558">"ચલાવો અથવા થોભાવો"</string>
+    <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"ઝડપી ફોરવર્ડ કરો"</string>
+    <string name="play_controls_description_fast_rewind" msgid="953488122681015803">"રીવાઇન્ડ કરો"</string>
+    <string name="play_controls_description_skip_next" msgid="1603587562124694592">"આગલું"</string>
+    <string name="play_controls_description_skip_previous" msgid="3858447678278021381">"પહેલાંનું"</string>
+    <string name="channels_item_program_guide" msgid="2889807207930678418">"પ્રોગ્રામ માર્ગદર્શિકા"</string>
+    <string name="channels_item_setup" msgid="6557412175737379022">"નવી ચૅનલો ઉપલબ્ધ છે"</string>
+    <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"<xliff:g id="APP_NAME">%1$s</xliff:g> ખોલો"</string>
+    <string name="options_item_closed_caption" msgid="5945274655046367170">"ઉપશીર્ષક"</string>
+    <string name="options_item_display_mode" msgid="7989243076748680140">"પ્રદર્શન મોડ"</string>
+    <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
+    <string name="options_item_multi_audio" msgid="5118851311937896923">"બહુ-ઑડિઓ"</string>
+    <string name="options_item_more_channels" msgid="971040969622943300">"વધુ ચૅનલો મેળવો"</string>
+    <string name="options_item_settings" msgid="7623205838542400074">"સેટિંગ્સ"</string>
+    <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (એન્ટેના/કેબલ)"</string>
+    <string name="no_program_information" msgid="1049844207745145132">"કોઈ પ્રોગ્રામ માહિતી નથી"</string>
+    <string name="program_title_for_no_information" msgid="384451471906070101">"કોઈ માહિતી નથી"</string>
+    <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"અવરોધિત કરેલ ચૅનલ"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"અજાણ ભાષા"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"ઉપશીર્ષક %1$d"</string>
+    <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"ઉપશીર્ષક"</string>
+    <string name="closed_caption_option_item_off" msgid="4824009036785647753">"બંધ"</string>
+    <string name="closed_caption_system_settings" msgid="1856974607743827178">"કસ્ટમાઇઝ ફૉર્મેટિંગ"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"ઉપશીર્ષક માટે સિસ્ટમ-વ્યાપી પસંદગીઓ સેટ કરો"</string>
+    <string name="side_panel_title_display_mode" msgid="6346286034015991229">"પ્રદર્શન મોડ"</string>
+    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"બહુ-ઑડિઓ"</string>
+    <string name="multi_audio_channel_mono" msgid="6229173848963557723">"મૉનો"</string>
+    <string name="multi_audio_channel_stereo" msgid="3758995659214256587">"સ્ટીરિઓ"</string>
+    <string name="multi_audio_channel_surround_6" msgid="6066304966228963942">"5.1 સરાઉન્ડ"</string>
+    <string name="multi_audio_channel_surround_8" msgid="2765140653768694313">"7.1 સરાઉન્ડ"</string>
+    <string name="multi_audio_channel_suffix" msgid="4443825738196093772">"%d ચૅનલ"</string>
+    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"ચૅનલની સૂચિ કસ્ટમાઇઝ કરો"</string>
+    <string name="edit_channels_item_select_group" msgid="4953000352257999703">"જૂથ પસંદ કરો"</string>
+    <string name="edit_channels_item_deselect_group" msgid="5092649099546997807">"જૂથની પસંદગી દૂર કરો"</string>
+    <string name="edit_channels_item_group_by" msgid="7794571851966798199">"આ દ્વારા જૂથબદ્ધ કરો"</string>
+    <string name="edit_channels_group_by_sources" msgid="5481053601210461217">"ચૅનલ સ્રોત"</string>
+    <string name="edit_channels_group_by_hd_sd" msgid="5582719665718278819">"HD/SD"</string>
+    <string name="edit_channels_group_divider_for_hd" msgid="5311355566660389423">"HD"</string>
+    <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
+    <string name="side_panel_title_group_by" msgid="1783176601425788939">"આ દ્વારા જૂથબદ્ધ કરો"</string>
+    <string name="program_guide_content_locked" msgid="198056836554559553">"આ પ્રોગ્રામ અવરોધિત કરેલ છે"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"આ પ્રોગ્રામ અનરેટેડ છે"</string>
+    <string name="program_guide_content_locked_format" msgid="514915272862967389">"આ પ્રોગ્રામને <xliff:g id="RATING">%1$s</xliff:g> રેટ કરેલ છે"</string>
+    <string name="msg_no_setup_activity" msgid="7746893144640239857">"ઇનપુટ સ્વતઃ સ્કૅનને સમર્થન આપતું નથી"</string>
+    <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' માટે સ્વતઃ સ્કૅન શરૂ કરવામાં અસમર્થ"</string>
+    <string name="msg_unable_to_start_system_captioning_settings" msgid="705242616044165668">"ઉપશીર્ષક માટે સિસ્ટમ-વ્યાપી પસંદગીઓ શરૂ કરવામાં અસમર્થ."</string>
+    <plurals name="msg_channel_added" formatted="false" msgid="5301526166755938705">
+      <item quantity="one">%1$d ચૅનલ ઉમેરી</item>
+      <item quantity="other">%1$d ચૅનલ ઉમેરી</item>
+    </plurals>
+    <string name="msg_no_channel_added" msgid="2882586037409921925">"કોઈ ચૅનલો ઉમેરી નથી"</string>
+    <string name="menu_parental_controls" msgid="2474294054521345840">"માતા પિતા યોગ્ય નિયંત્રણો"</string>
+    <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ચાલુ"</string>
+    <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"બંધ"</string>
+    <string name="option_channels_locked" msgid="5797855082297549907">"અવરોધિત કરેલ ચૅનલો"</string>
+    <string name="option_channels_lock_all" msgid="6594512884477342940">"તમામને અવરોધિત કરો"</string>
+    <string name="option_channels_unlock_all" msgid="6839513296447567623">"તમામને અનાવરોધિત કરો"</string>
+    <string name="option_channels_subheader_hidden" msgid="4669425935426972078">"છુપાયેલ ચૅનલો"</string>
+    <string name="option_program_restrictions" msgid="241342023067364108">"પ્રોગ્રામ પ્રતિબંધો"</string>
+    <string name="option_change_pin" msgid="2881594075631152566">"PIN બદલો"</string>
+    <string name="option_country_rating_systems" msgid="7288569813945260224">"રેટિંગ સિસ્ટમ"</string>
+    <string name="option_ratings" msgid="4009116954188688616">"રેટિંગ"</string>
+    <string name="option_see_all_rating_systems" msgid="7702673500014877288">"તમામ રેટિંંગ સિસ્ટમ જુઓ"</string>
+    <string name="other_countries" msgid="8342216398676184749">"અન્ય દેશો"</string>
+    <string name="option_no_locked_channel" msgid="2543094883927978444">"કોઈ નહીં"</string>
+    <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"કોઈ નહીં"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"અનરેટેડ"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"અનરેટેડ પ્રોગ્રામ બ્લૉક કરો"</string>
+    <string name="option_rating_none" msgid="5204552587760414879">"કોઈ નહીં"</string>
+    <string name="option_rating_high" msgid="8898400296730158893">"વધુ પ્રતિબંધો"</string>
+    <string name="option_rating_medium" msgid="6455853836426497151">"મધ્યમ પ્રતિબંધો"</string>
+    <string name="option_rating_low" msgid="5800146024503377969">"ઓછા પ્રતિબંધો"</string>
+    <string name="option_rating_custom" msgid="3155377834510646436">"કસ્ટમ"</string>
+    <string name="option_rating_high_description" msgid="609567565273278745">"સામગ્રી બાળકો માટે યોગ્ય છે"</string>
+    <string name="option_rating_medium_description" msgid="7169199016608935280">"સામગ્રી મોટા બાળકો માટે યોગ્ય છે"</string>
+    <string name="option_rating_low_description" msgid="4740109576615335045">"સામગ્રી કિશોરો માટે યોગ્ય છે"</string>
+    <string name="option_rating_custom_description" msgid="6180723522991233194">"મેન્યુઅલ પ્રતિબંધો"</string>
+    <string name="option_attribution" msgid="2967657807178951562">"વર્ણનોને રેટ કરવા માટે સ્રોતો"</string>
+    <string name="option_subrating_title" msgid="5485055507818077595">"%1$s અને પેટા-રેટિંગ"</string>
+    <string name="option_subrating_header" msgid="4637961301549615855">"પેટા-રેટિંગ"</string>
+    <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"આ ચૅનલ જોવા માટે તમારો PIN દાખલ કરો"</string>
+    <string name="pin_enter_unlock_program" msgid="7311628843209871203">"આ પ્રોગ્રામ જોવા માટે તમારો PIN દાખલ કરો"</string>
+    <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"આ પ્રોગ્રામ <xliff:g id="RATING">%1$s</xliff:g> રેટ કરેલ છે. આ પ્રોગ્રામ જોવા માટે તમારો PIN દાખલ કરો"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"આ પ્રોગ્રામ અનરેટેડ છે. આ પ્રોગ્રામ જોવા માટે તમારો પિન દાખલ કરો"</string>
+    <string name="pin_enter_pin" msgid="249314665028035038">"તમારો PIN દાખલ કરો"</string>
+    <string name="pin_enter_create_pin" msgid="3385754356793309946">"માતા પિતા યોગ્ય નિયંત્રણો સેટ કરવા માટે, એક PIN બનાવો"</string>
+    <string name="pin_enter_new_pin" msgid="1739471585849790384">"નવો PIN દાખલ કરો"</string>
+    <string name="pin_enter_again" msgid="2618999754723090427">"તમારા PIN ની પુષ્ટિ કરો"</string>
+    <string name="pin_enter_old_pin" msgid="4588282612931041919">"તમારો વર્તમાન PIN દાખલ કરો"</string>
+    <plurals name="pin_enter_countdown" formatted="false" msgid="3415233538538544309">
+      <item quantity="one">તમે 5 વખત ખોટો PIN દાખલ કર્યો.\n<xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> સેકન્ડમાંં ફરી પ્રયાસ કરો.</item>
+      <item quantity="other">તમે 5 વખત ખોટો PIN દાખલ કર્યો.\n<xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> સેકન્ડમાંં ફરી પ્રયાસ કરો.</item>
+    </plurals>
+    <string name="pin_toast_wrong" msgid="2126295626095048746">"તે PIN ખોટો હતો. ફરી પ્રયાસ કરો."</string>
+    <string name="pin_toast_not_match" msgid="4283624338659521768">"ફરીથી પ્રયાસ કરો, PIN મેળ ખાતો નથી"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"તમારો પિન કોડ દાખલ કરો."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"TV ચૅનલો માટે એક સંપૂર્ણ પ્રોગ્રામ માર્ગદર્શિકા પ્રદાન કરવા માટે લાઇવ ચૅનલ ઍપ્લિકેશન પિન કોડનો ઉપયોગ કરશે."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"તમારો પિન કોડ દાખલ કરો"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"અમાન્ય પિન કોડ"</string>
+    <string name="side_panel_title_settings" msgid="8244327316510918755">"સેટિંગ્સ"</string>
+    <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"ચૅનલની સૂચિ કસ્ટમાઇઝ કરો"</string>
+    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"તમારી પ્રોગ્રામ માર્ગદર્શિકા માટે ચૅનલો પસંદ કરો"</string>
+    <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"ચૅનલ સ્રોત"</string>
+    <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"નવી ચૅનલો ઉપલબ્ધ છે"</string>
+    <string name="settings_parental_controls" msgid="5449397921700749317">"માતા પિતા યોગ્ય નિયંત્રણો"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"સમય અંતરાલ"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"જોતી વખતે રેકોર્ડ કરો, જેથી તમે લાઇવ પ્રોગ્રામને થોભાવી અથવા રીવાઇન્ડ કરી શકો છો.\nચેતવણી: સ્ટૉરેજનાં સઘન ઉપયોગને કારણે આ આંતરિક સ્ટૉરેજની આવરદાને ઘટાડી શકે છે."</string>
+    <string name="settings_menu_licenses" msgid="1257646083838406103">"ખુલ્લા સ્ત્રોત લાઇસન્સ"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"પ્રતિસાદ મોકલો"</string>
+    <string name="settings_menu_version" msgid="2604030372029921403">"સંસ્કરણ"</string>
+    <string name="tvview_channel_locked" msgid="6486375335718400728">"આ ચૅનલ જોવા માટે, જમણે દબાવો અને તમારો PIN દાખલ કરો."</string>
+    <string name="tvview_content_locked" msgid="391823084917017730">"આ પ્રોગ્રામ જોવા માટે, જમણે દબાવો અને તમારો PIN દાખલ કરો."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"આ પ્રોગ્રામ અનરેટેડ છે.\nઆ પ્રોગ્રામ જોવા માટે, જમણે દબાવો અને તમારો પિન દાખલ કરો"</string>
+    <string name="tvview_content_locked_format" msgid="3741874636031338247">"આ પ્રોગ્રામને <xliff:g id="RATING">%1$s</xliff:g> રેેેટ કરેલ છે.\nઆ પ્રોગ્રામ જોવા માટે, જમણે દબાવો અને તમારો PIN દાખલ કરો."</string>
+    <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"આ ચૅનલ જોવા માટે, ડિફૉલ્ટ લાઇવ TV ઍપ્લિકેશનનો ઉપયોગ કરો."</string>
+    <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"આ પ્રોગ્રામ જોવા માટે, ડિફૉલ્ટ લાઇવ TV ઍપ્લિકેશનનો ઉપયોગ કરો."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"આ પ્રોગ્રામ અનરેટેડ છે.\nઆ પ્રોગ્રામ જોવા માટે, ડિફૉલ્ટ લાઇવ TV ઍપનો ઉપયોગ કરો."</string>
+    <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"આ પ્રોગ્રામને <xliff:g id="RATING">%1$s</xliff:g> રેેેટ કરેલ છે.\nઆ પ્રોગ્રામ જોવા માટે, ડિફૉલ્ટ લાઇવ TV ઍપ્લિકેશનનો ઉપયોગ કરો."</string>
+    <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"પ્રોગ્રામ અવરોધિત કરેલ છે"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"આ પ્રોગ્રામ અનરેટેડ છે"</string>
+    <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"આ પ્રોગ્રામ <xliff:g id="RATING">%1$s</xliff:g> રેટ કરેલ છે"</string>
+    <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ફક્ત ઑડિઓ"</string>
+    <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"નબળા સંકેત"</string>
+    <string name="tvview_msg_no_internet_connection" msgid="7655994401188888231">"કોઈ ઇન્ટરનેટ કનેક્શન નથી"</string>
+    <plurals name="tvview_msg_input_no_resource" formatted="false" msgid="8581894855153658823">
+      <item quantity="one">આ ચૅનલ <xliff:g id="END_TIME_1">%1$s</xliff:g> સુધી ચલાવી શકાશે નહીં કારણ કે અન્ય ચૅનલો રેકોર્ડ થઈ રહી છે. \n\nરેકોર્ડિંગ શેડ્યૂલ ગોઠવવા માટે જમણે દબાવો.</item>
+      <item quantity="other">આ ચૅનલ <xliff:g id="END_TIME_1">%1$s</xliff:g> સુધી ચલાવી શકાશે નહીં કારણ કે અન્ય ચૅનલો રેકોર્ડ થઈ રહી છે. \n\nરેકોર્ડિંગ શેડ્યૂલ ગોઠવવા માટે જમણે દબાવો.</item>
+    </plurals>
+    <string name="channel_banner_no_title" msgid="8660301979190693176">"કોઈ શીર્ષક નથી"</string>
+    <string name="channel_banner_locked_channel_title" msgid="2006564967318945980">"ચૅનલ અવરોધિત કરી"</string>
+    <string name="setup_category_new" msgid="2899355289563443627">"નવું"</string>
+    <string name="setup_category_done" msgid="4750902502852212319">"સ્રોતો"</string>
+    <plurals name="setup_input_channels" formatted="false" msgid="1695941684075602971">
+      <item quantity="one">%1$d ચૅનલ</item>
+      <item quantity="other">%1$d ચૅનલ</item>
+    </plurals>
+    <string name="setup_input_no_channels" msgid="1669327912393163331">"કોઈ ચૅનલો ઉપલબ્ધ નથી"</string>
+    <string name="setup_input_new" msgid="3337725672277046798">"નવું"</string>
+    <string name="setup_input_setup_now" msgid="1772000402336958967">"સેટ કરેલ નથી"</string>
+    <string name="setup_store_action_title" msgid="4083402039720973414">"વધુ સ્રોત મેળવો"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"લાઇવ ચૅનલો ઑફર કરતી ઍપ્લિકેશનો બ્રાઉઝ કરો"</string>
+    <string name="new_sources_title" msgid="3878933676500061895">"નવી ચૅનલનાં સ્રોત ઉપલબ્ધ છે"</string>
+    <string name="new_sources_description" msgid="749649005588426813">"નવા ચૅનલ સ્રોત પાસે ઑફર કરવા માટે ચૅનલો છે.\nતેમને હમણાં જ સેટ કરો અથવા ચૅનલ સ્રોત સેટિંગમાં પછીથી આ કરી શકો છો."</string>
+    <string name="new_sources_action_setup" msgid="177693761664016811">"હવે સેટ કરો"</string>
+    <string name="new_sources_action_skip" msgid="2501296961258184330">"બરાબર, સમજાઇ ગયું"</string>
+    <!-- no translation found for intro_title (251772896916795556) -->
+    <skip />
+    <string name="intro_description" msgid="7806473686446937307">"TV મેનૂને ઍક્સેસ કરવા માટે "<b>"પસંદ કરો દબાવો"</b>"."</string>
+    <string name="msg_no_input" msgid="3897674146985427865">"કોઈ TV ઇનપુટ મળ્યું નથી"</string>
+    <string name="msg_no_specific_input" msgid="2688885987104249852">"TV ઇનપુટ શોધી શકાતું નથી"</string>
+    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ટ્યૂનર પ્રકાર યોગ્ય નથી. કૃપા કરીને ટ્યૂનર પ્રકાર TV ઇનપુટ માટે લાઇવ ચૅનલો લોંચ કરો."</string>
+    <string name="msg_tune_failed" msgid="3277419551849972252">"ટ્યૂન કરવાનું નિષ્ફળ થયું"</string>
+    <string name="msg_missing_app" msgid="8291542072400042076">"આ ક્રિયાને હેન્ડલ કરવા માટે કોઈ ઍપ્લિકેશન મળી નહીં."</string>
+    <string name="msg_all_channels_hidden" msgid="777397634062471936">"તમામ સ્રોત ચૅનલો છુપાયેલા છે.\nજોવા માટે ઓછામાં ઓછી એક ચૅનલ પસંદ કરો."</string>
+    <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"વિડિઓ અનપેક્ષિત રીતે અનુપલબ્ધ છે"</string>
+    <string name="msg_back_key_guide" msgid="7404682718828721924">"પાછળ કી કનેક્ટ કરેલ ઉપકરણ માટે છે. બહાર નીકળવા માટે હોમ બટન દબાવો."</string>
+    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"TVની સૂચિ વાંચવા માટે લાઇવ ચૅનલોને પરવાનગીની જરૂર છે."</string>
+    <string name="setup_sources_text" msgid="4988039637873759839">"તમારા સ્રોત સેટઅપ કરો"</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"લાઇવ ચૅનલો પરંપરાગત TV ચૅનલોનાં અનુભવને ઍપ્લિકેશનો દ્વારા પ્રદાન કરેક સ્ટ્રીમિંગ ચૅનલો સાથે ભેગો કરે છે. \n\nપહેલેથી ઇન્સ્ટૉલ કરેલ હોય તે ચૅનલ સ્રોતોને સેટ કરીને પ્રારંભ કરો. અથવા Google Play સ્ટોર બ્રાઉઝ કરો."</string>
+    <string name="channels_item_dvr" msgid="8911915252648532469">"રેકોર્ડિંગ અને શેડ્યૂલ"</string>
+    <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 મિનિટ"</string>
+    <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 મિનિટ"</string>
+    <string name="recording_start_dialog_1_hour_duration" msgid="7159533207022355641">"1 કલાક"</string>
+    <string name="recording_start_dialog_3_hours_duration" msgid="295984419320006238">"3 કલાક"</string>
+    <string name="dvr_main_recent" msgid="2553805424822806495">"તાજેતરના"</string>
+    <string name="dvr_main_scheduled" msgid="7837260963086408492">"શેડ્યૂલ કરેલ"</string>
+    <string name="dvr_main_series" msgid="8278256687595691676">"શ્રૃંખલા"</string>
+    <string name="dvr_main_others" msgid="2970835573614038153">"અન્ય"</string>
+    <string name="dvr_msg_cannot_record_channel" msgid="6836291367918532447">"ચૅનલ રેકોર્ડ કરી શકાતી નથી."</string>
+    <string name="dvr_msg_cannot_record_program" msgid="4184046342810946090">"પ્રોગ્રામ રેકોર્ડ કરી શકાતો નથી."</string>
+    <string name="dvr_msg_program_scheduled" msgid="3800847542300367572">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> રેકોર્ડ થવા માટે શેડ્યૂલ કરવામાં આવ્યો છે"</string>
+    <string name="dvr_msg_current_program_scheduled" msgid="2505247201782991463">"હવેથી <xliff:g id="ENDTIME">%2$s</xliff:g> સુધી <xliff:g id="PROGRAMNAME">%1$s</xliff:g> રેકોર્ડ કરાશે"</string>
+    <string name="dvr_full_schedule_card_view_title" msgid="7198521806965950089">"સંપૂર્ણ શેડ્યૂલ"</string>
+    <plurals name="dvr_full_schedule_card_view_content" formatted="false" msgid="790788122541080768">
+      <item quantity="one">આગલાં %1$d દિવસ</item>
+      <item quantity="other">આગલાં %1$d દિવસ</item>
+    </plurals>
+    <plurals name="dvr_program_duration" formatted="false" msgid="6742119148312354741">
+      <item quantity="one">%1$d મિનિટ</item>
+      <item quantity="other">%1$d મિનિટ</item>
+    </plurals>
+    <plurals name="dvr_count_new_recordings" formatted="false" msgid="3569310208305402815">
+      <item quantity="one">%1$d નવા રેકોર્ડિંગ</item>
+      <item quantity="other">%1$d નવા રેકોર્ડિંગ</item>
+    </plurals>
+    <plurals name="dvr_count_recordings" formatted="false" msgid="7417379223468131391">
+      <item quantity="one">%1$d રેકોર્ડિંગ</item>
+      <item quantity="other">%1$d રેકોર્ડિંગ</item>
+    </plurals>
+    <plurals name="dvr_count_scheduled_recordings" formatted="false" msgid="1650330290765214511">
+      <item quantity="one">%1$d રેકોર્ડિંગ શેડ્યૂલ કર્યા</item>
+      <item quantity="other">%1$d રેકોર્ડિંગ શેડ્યૂલ કર્યા</item>
+    </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"રેકોર્ડિંગ રદ કરો"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"રેકોર્ડિંગ રોકો"</string>
+    <string name="dvr_detail_watch" msgid="7085694764364338215">"ઘડિયાળ"</string>
+    <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"શરૂઆતથી ચલાવો"</string>
+    <string name="dvr_detail_resume_play" msgid="875591300274416373">"ચલાવવાનું ફરી શરૂ કરો"</string>
+    <string name="dvr_detail_delete" msgid="4535881013528321898">"કાઢી નાખો"</string>
+    <string name="dvr_detail_series_delete" msgid="4831926831670312674">"રેકોર્ડિંગ કાઢી નાખો"</string>
+    <string name="dvr_detail_series_resume" msgid="6935136228671386246">"ફરી શરૂ કરો"</string>
+    <string name="dvr_detail_series_season_title" msgid="5474850936497854790">"સિઝન <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>"</string>
+    <string name="dvr_detail_view_schedule" msgid="7137536927421904426">"શેડ્યૂલ જુઓ"</string>
+    <string name="dvr_detail_read_more" msgid="2588920758094498544">"વધુ વાંચો"</string>
+    <string name="dvr_series_deletion_title" msgid="7672649492494507574">"રેકોર્ડિંગ કાઢી નાખો"</string>
+    <string name="dvr_series_deletion_description" msgid="994839237906552969">"તમે કાઢી નાખવા માગતા હોય તે એપિસોડ પસંદ કરો. એક વાર કાઢી નાખ્યા પછી તે પુનઃપ્રાપ્ત કરી શકાશે નહીં."</string>
+    <string name="dvr_series_deletion_no_recordings" msgid="481210819034514">"કાઢી શકાય તેવું કોઈ રેકોર્ડિંગ નથી."</string>
+    <string name="dvr_series_select_watched" msgid="3608122404146716502">"જોયેલા એપિસોડ પસંદ કરો"</string>
+    <string name="dvr_series_select_all" msgid="5415749261739544048">"તમામ એપિસોડ પસંદ કરો"</string>
+    <string name="dvr_series_deselect_all" msgid="1680395960166387572">"તમામા એપિસોડની પસંદગી દૂર કરો"</string>
+    <string name="dvr_series_watched_info_minutes" msgid="5656926431901526030">"<xliff:g id="DURATION">%2$d</xliff:g> માંથી <xliff:g id="WATCHED">%1$d</xliff:g> મિનિટની રેકોર્ડિંગ જોઈ"</string>
+    <string name="dvr_series_watched_info_seconds" msgid="2667537184197566662">"<xliff:g id="DURATION">%2$d</xliff:g> માંથી <xliff:g id="WATCHED">%1$d</xliff:g> સેકન્ડની રેકોર્ડિંગ જોઈ"</string>
+    <string name="dvr_series_never_watched" msgid="6086008065876122655">"ક્યારેય જોઈ નથી"</string>
+    <plurals name="dvr_msg_episodes_deleted" formatted="false" msgid="5627112959798353905">
+      <item quantity="one">%2$dમાંથી %1$d એપિસોડ કાઢી નાખ્યાં</item>
+      <item quantity="other">%2$dમાંથી %1$d એપિસોડ કાઢી નાખ્યાં</item>
+    </plurals>
+    <string name="dvr_series_settings_priority" msgid="5836437092774185710">"પ્રાધાન્યતા"</string>
+    <string name="dvr_series_settings_priority_highest" msgid="1072006447796648382">"સૌથી ઉચ્ચ"</string>
+    <string name="dvr_series_settings_priority_lowest" msgid="6003996497908810225">"ન્યૂનતમ"</string>
+    <string name="dvr_series_settings_priority_rank" msgid="667778382820956116">"નં. <xliff:g id="RANK">%1$d</xliff:g>"</string>
+    <string name="dvr_series_settings_channels" msgid="3164900110165729909">"ચૅનલો"</string>
+    <string name="dvr_series_settings_channels_all" msgid="656434955168572976">"કોઈપણ"</string>
+    <string name="dvr_priority_title" msgid="1537886929061487213">"પ્રાધાન્યતા પસંદ કરો"</string>
+    <string name="dvr_priority_description" msgid="8362040921417154645">"જ્યારે એક જ સમયે રેકોર્ડ કરવા માટે ઘણાં બધા પ્રોગ્રામ હોય છે, ત્યારે વધુ પ્રાધાન્યતાવાળા પ્રોગ્રામ જ રેકોર્ડ કરાશે."</string>
+    <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"સાચવો"</string>
+    <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"એક-વારની રેકોર્ડિંગની સૌથી વધુ પ્રાધાન્યતા હોય છે"</string>
+    <string name="dvr_action_stop" msgid="1378723485295471381">"રોકો"</string>
+    <string name="dvr_action_view_schedules" msgid="7442990695392774263">"રેકોર્ડિંગ શેડ્યૂલ જુઓ"</string>
+    <string name="dvr_action_record_episode" msgid="8596182676610326327">"આ એકલ પ્રોગ્રામ"</string>
+    <string name="dvr_action_record_episode_from_now_description" msgid="5125122951529985697">"હવેથી - <xliff:g id="ENDTIME">%1$s</xliff:g>"</string>
+    <string name="dvr_action_record_series" msgid="8501991316179436899">"સમગ્ર શ્રૃંખલા…"</string>
+    <string name="dvr_action_record_anyway" msgid="991470058034937231">"કોઈપણ રીતે શેડ્યૂલ કરો"</string>
+    <string name="dvr_action_record_instead" msgid="6821164728752215738">"તેને બદલે આ રેકોર્ડ કરો"</string>
+    <string name="dvr_action_record_cancel" msgid="8644254745772185288">"આ રેકોર્ડિંગ રદ કરો"</string>
+    <string name="dvr_action_watch_now" msgid="7181211920959075976">"હમણાં જુઓ"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"રેકોર્ડિંગ કાઢી નાખો…"</string>
+    <string name="dvr_epg_program_recordable" msgid="609229576209476903">"રેકોર્ડ કરવા યોગ્ય"</string>
+    <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"રેકોર્ડિંગ શેડ્યૂલ કર્યું"</string>
+    <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"રેકોર્ડિંગ વિરોધ"</string>
+    <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"રેકોર્ડ કરી રહ્યું છે"</string>
+    <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"રેકોર્ડ કરવાનું નિષ્ફળ થયું"</string>
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"પ્રોગ્રામની માહિતી વાંચી રહી છે"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"તાજેતરનું રેકોર્ડિંગ જુઓ"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>નું રેકોર્ડિંગ અધૂરું છે."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> અને <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>નું રેકોર્ડિંગ અધૂરું છે."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> અને <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>નું રેકોર્ડિંગ અધૂરું છે."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"અપર્યાપ્ત સ્ટોરેજને કારણે <xliff:g id="PROGRAMNAME">%1$s</xliff:g>નું રેકોર્ડિંગ પૂર્ણ થયું નથી."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"અપર્યાપ્ત સ્ટોરેજને કારણે <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> અને <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>નું રેકોર્ડિંગ પૂર્ણ થયું નથી."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"અપર્યાપ્ત સ્ટોરેજને કારણે <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> અને <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>નું રેકોર્ડિંગ પૂર્ણ થયું નથી."</string>
+    <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVRને વધુ સ્ટોરેજની જરૂર છે"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"તમે DVR વડે પ્રોગ્રામ રેકોર્ડ કરી શકશો. જોકે, હમણાં તમારા ઉપકરણ પર DVR કાર્ય કરી શકે તે માટે પર્યાપ્ત સ્ટોરેજ નથી. કૃપા કરીને <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB અથવા તેનાથી મોટી બાહ્યાં ડ્રાઇવ કનેક્ટ કરો અને તેને ઉપકરણ સ્ટોરેજ તરીકે ફૉર્મેટ કરવા માટે પગલાં અનુસરો."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"પર્યાપ્ત સ્ટોરેજ ઉપલબ્ધ નથી"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"પર્યાપ્ત સ્ટોરેજ ન હોવાને કારણે આ પ્રોગ્રામ રેકોર્ડ કરાશે નહીં. કેટલીક અસ્તિત્વમાંની રેકોર્ડિંગને કાઢી નાખીને ફરી પ્રયાસ કરો."</string>
+    <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"સ્ટોરેજ ખૂટે છે"</string>
+    <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"રેકોર્ડિંગ રોકીએ?"</string>
+    <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"રેકોર્ડ કરેલ સામગ્રી સાચવવામાં આવશે."</string>
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>નું રેકોર્ડિંગ બંધ થશે કારણ કે તે આ પ્રોગ્રામ સાથે વિરોધાભાસી છે. રેકોર્ડ કરેલ સામગ્રી સાચવવામાં આવશે."</string>
+    <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"રેકોર્ડિંગ શેડ્યૂલ કરી પણ તે વિરોધાભાસી છે"</string>
+    <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"રેકોર્ડિંગ શરૂ થઈ ગઈ છે પરંતુ તે વિરોધાભાસી છે"</string>
+    <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> રેકોર્ડ કરવામાં આવશે."</string>
+    <string name="dvr_channel_conflict_dialog_description_prefix" msgid="212344250779878791">"<xliff:g id="CHANNELNAME">%1$s</xliff:g> રેકોર્ડ થઈ રહી છે."</string>
+    <string name="dvr_program_conflict_dialog_description_1" msgid="2278200346765501164">"<xliff:g id="CONFLICTPROGRAMNAME">%1$s</xliff:g>નાં કેટલાક ભાગો રેકોર્ડ કરવામાં આવશે નહીં."</string>
+    <string name="dvr_program_conflict_dialog_description_2" msgid="5648524408147235696">"<xliff:g id="CONFLICTPROGRAMNAME_1">%1$s</xliff:g> અને <xliff:g id="CONFLICTPROGRAMNAME_2">%2$s</xliff:g>નાં કેટલાક ભાગો રેકોર્ડ કરવામાં આવશે નહીં."</string>
+    <string name="dvr_program_conflict_dialog_description_3" msgid="6879199850098595108">"<xliff:g id="CONFLICTPROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2">%2$s</xliff:g> અને વધુ એક શેડ્યૂલનાં કેટલાક ભાગો રેકોર્ડ કરવામાં આવશે નહીં."</string>
+    <plurals name="dvr_program_conflict_dialog_description_many" formatted="false" msgid="1008340710252647947">
+      <item quantity="one"><xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> અને વધુ %3$d શેડ્યૂલનાં ભાગો રેકોર્ડ કરવામાં આવશે નહીં.</item>
+      <item quantity="other"><xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> અને વધુ %3$d શેડ્યૂલનાં ભાગો રેકોર્ડ કરવામાં આવશે નહીં.</item>
+    </plurals>
+    <string name="dvr_schedule_dialog_title" msgid="5235629824986156058">"તમે શું રેકોર્ડ કરવા માગો છો?"</string>
+    <string name="dvr_channel_record_duration_dialog_title" msgid="4601361040431047918">"તમે કેટલી વાર સુધી રેકોર્ડ કરવા માગો છો?"</string>
+    <string name="dvr_already_scheduled_dialog_title" msgid="4525318291210934311">"પહેલેથી શેડ્યૂલ કરેલ છે"</string>
+    <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"આ જ પ્રોગ્રામ <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> વાગ્યે રેકોર્ડ કરવા માટે શેડ્યૂલ કરેલ છે."</string>
+    <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"પહેલેથી રેકોર્ડ કરેલ છે"</string>
+    <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"આ પ્રોગ્રામ પહેલેથી રેકોર્ડ કરેલો છે. તે DVR લાઇબ્રેરીમાં ઉપલબ્ધ છે."</string>
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"શ્રૃંખલા રેકોર્ડિંગ શેડ્યૂલ કરેલ છે"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે. વિરોધને કારણે તેમાંથી <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>ને રેકોર્ડ કરવામાં આવશે નહીં.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે. વિરોધને કારણે તેમાંથી <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>ને રેકોર્ડ કરવામાં આવશે નહીં.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે. વિરોધને કારણે આ શ્રૃંખલા અને અન્ય શ્રૃંખલાનાં <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> એપિસોડ રેકોર્ડ કરવામાં આવશે નહીં.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે. વિરોધને કારણે આ શ્રૃંખલા અને અન્ય શ્રૃંખલાનાં <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> એપિસોડ રેકોર્ડ કરવામાં આવશે નહીં.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે. વિરોધને કારણે અન્ય શ્રૃંખલાનો 1 એપિસોડ રેકોર્ડ કરાશે નહીં.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે. વિરોધને કારણે અન્ય શ્રૃંખલાનો 1 એપિસોડ રેકોર્ડ કરાશે નહીં.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે. વિરોધને કારણે અન્ય શ્રૃંખલાનાં <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> એપિસોડ રેકોર્ડ કરાશે નહીં.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> રેકોર્ડિંગ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> માટે શેડ્યૂલ કરવામાં આવ્યાં છે. વિરોધને કારણે અન્ય શ્રૃંખલાનાં <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> એપિસોડ રેકોર્ડ કરાશે નહીં.</item>
+    </plurals>
+    <string name="dvr_program_not_found" msgid="3282879532038010202">"રેકોર્ડ કરેલ પ્રોગ્રામ મળ્યોં નથી."</string>
+    <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"સંબંધિત રેકોર્ડિંગ"</string>
+    <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
+      <item quantity="one">%1$d રેકોર્ડિંગ</item>
+      <item quantity="other">%1$d રેકોર્ડિંગ</item>
+    </plurals>
+    <string name="dvr_schedules_information_separator" msgid="1669116853379998479">" / "</string>
+    <string name="dvr_schedules_deletion_info" msgid="2837586459900271031">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>ને રેકોર્ડિંગ શેડ્યૂલથી દૂર કરાયો"</string>
+    <string name="dvr_schedules_tuner_conflict_will_be_partially_recorded" msgid="5280490298546908729">"ટ્યૂનર વિરોધને કારણે તે આંશિક રીતે રોકોર્ડ કરાશે."</string>
+    <string name="dvr_schedules_tuner_conflict_will_not_be_recorded_info" msgid="5065400564003201095">"ટ્યૂનર વિરોધને કારણે તે રોકોર્ડ કરાશે નહીં."</string>
+    <string name="dvr_schedules_empty_state" msgid="1291529283469462741">"હજી સુધી શેડ્યૂલ કરેલ કોઈ રેકોર્ડિંગ નથી.\nતમે પ્રોગ્રામ માર્ગદર્શિકાથી રેકોર્ડિંગને શેડ્યૂલ કરી શકો છો."</string>
+    <plurals name="dvr_series_schedules_header_description" formatted="false" msgid="9077188267856194114">
+      <item quantity="one">%1$d રેકોર્ડિંગ વિરોધ</item>
+      <item quantity="other">%1$d રેકોર્ડિંગ વિરોધ</item>
+    </plurals>
+    <string name="dvr_series_schedules_settings" msgid="4868501926847903985">"શ્રૃંખલા સેટિંગ્સ"</string>
+    <string name="dvr_series_schedules_start" msgid="8458768834047133835">"શ્રૃંખલા રેકોર્ડ કરવાનું શરૂ કરો"</string>
+    <string name="dvr_series_schedules_stop" msgid="3427479298317584961">"શ્રૃંખલા રેકોર્ડ કરવાનું રોકો"</string>
+    <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"શ્રૃંખલા રેકોર્ડ કરવાનું રોકીએ?"</string>
+    <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"રેકોર્ડ કરેલા એપિસોડ DVR લાઇબ્રેરીમાં ઉપલબ્ધ રહેશે."</string>
+    <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"રોકો"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"હમણાં કોઈ એપિસોડ પ્રસારિત થઈ રહ્યાં નથી."</string>
+    <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"કોઈ એપિસોડ ઉપલબ્ધ નથી.\nતે ઉપલબ્ધ હશે ત્યારે રેકોર્ડ કરવામાં આવશે."</string>
+    <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
+      <item quantity="one">(%1$d મિનિટ)</item>
+      <item quantity="other">(%1$d મિનિટ)</item>
+    </plurals>
+    <string name="dvr_date_today" msgid="7691050705354303471">"આજે"</string>
+    <string name="dvr_date_tomorrow" msgid="4136735681186981844">"આવતીકાલે"</string>
+    <string name="dvr_date_yesterday" msgid="2127672919053118239">"ગઈકાલે"</string>
+    <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> આજે"</string>
+    <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> આવતી કાલે"</string>
+    <string name="program_guide_critic_score" msgid="340530743913585150">"સ્કોર"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"રેકોર્ડ કરેલ પ્રોગ્રામ"</string>
+</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index d6db867..146bfa0 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"मोनो"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"स्टीरियो"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"चलाने के नियंत्रण"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"हाल ही के चैनल"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"चैनल"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"टीवी विकल्प"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP विकल्‍प"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"इस चैनल के लिए चलाने के नियंत्रण अनुपलब्‍ध हैं"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"चलाएं या रोकें"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"फ़ास्ट फ़ॉरवर्ड करें"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"उपशीर्षक"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"प्रदर्शन मोड"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"चालू"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"बंद"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"एकाधिक-ऑडियो"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"अधिक चैनल पाएं"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"सेटिंग"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"स्रोत"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"स्वैप करें"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"चालू"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"बंद"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ध्वनि"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"मुख्‍य"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP विंडो"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"लेआउट"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"नीचे दाएं"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ऊपर दाएं"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ऊपर बाएं"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"नीचे बाएं"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"साथ-साथ"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"आकार"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"बड़ा"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"छोटा"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"इनपुट स्रोत"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"टीवी (एंटिना/केबल)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"कोई कार्यक्रम जानकारी नहीं"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"कोई सूचना नहीं"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"अवरोधित चैनल"</string>
-    <string name="default_language" msgid="4122326459624337928">"अज्ञात भाषा"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"अज्ञात भाषा"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"बंद कैप्शन %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"उपशीर्षक"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"बंद"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"प्रारूपण कस्टमाइज़ करें"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"इसके द्वारा समूहीकृत"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"यह कार्यक्रम अवरोधित है"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"इस कार्यक्रम को रेट नहीं किया गया है"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"इस कार्यक्रम को <xliff:g id="RATING">%1$s</xliff:g> रेट किया गया है"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"इनपुट ऑटो-स्कैन का समर्थन नहीं करता है"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' के लिए स्वतः स्कैन प्रारंभ करने में असमर्थ"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d चैनल जोड़े गए</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"कोई चैनल नहीं जोड़ा गया"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ट्यूनर"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"अभिभावकीय नियंत्रण"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"चालू"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"बंद"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"अन्य देश"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"कोई नहीं"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"कोई नहीं"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"रेट नहीं किया गया"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"रेट नहीं किए गए कार्यक्रम ब्लॉक करें"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"कोई नहीं"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"उच्च प्रतिबंध"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"मध्यम प्रतिबंध"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"इस चैनल को देखने के लिए अपना पिन डालें"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"इस कार्यक्रम को देखने के लिए अपना पिन डालें"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"इस कार्यक्रम को <xliff:g id="RATING">%1$s</xliff:g> रेट किया गया है. यह कार्यक्रम देखने के लिए अपना पिन डालें"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"इस कार्यक्रम को रेट नहीं किया गया है. इसे देखने के लिए अपना पिन डालें"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"अपना पिन डालें"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"अभिभावकीय नियंत्रण सेट करने के लिए, पिन बनाएं"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"नया पिन डालें"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"वह पिन गलत था. पुन: प्रयास करें."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"फिर से प्रयास करें, पिन का मिलान नहीं हुआ"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"अपना ज़िप कोड डालें."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"लाइव चैनल ऐप्लिकेशन ज़िप कोड का उपयोग करके टीवी चैनल के लिए पूरी कार्यक्रम मार्गदर्शिका देगा."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"अपना ज़िप कोड डालें"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"अमान्य ज़िप कोड"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"सेटिंग"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"चैनल सूची कस्टमाइज़ करें"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"कार्यक्रम मार्गदर्शिका के लिए चैनल चुनें"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"चैनल के स्रोत"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"नए चैनल उपलब्‍ध हैं"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"अभिभावकीय नियंत्रण"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"टाइमशिफ़्ट"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"देखते समय रिकॉर्ड करें ताकि आप लाइव कार्यक्रमों को रोक सकें या उन्हें रिवाइंड कर पाएं.\nचेतावनी: यह जगह का बहुत ज़्यादा उपयोग करके आंतरिक जगह का जीवनकाल घटा सकता है."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"ओपन सोर्स लाइसेंस"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"ओपन सोर्स लाइसेंस"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"फ़ीडबैक भेजें"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"वर्शन"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"इस चैनल को देखने के लिए, दाईं ओर दबाएं और अपना पिन डालें"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"इस कार्यक्रम को देखने के लिए, दाईं ओर दबाएं और अपना पिन डालें"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"इस कार्यक्रम को रेट नहीं किया गया है.\nइसे देखने के लिए, कृपया दायां दबाएं और अपना पिन डालें"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"इस कार्यक्रम को <xliff:g id="RATING">%1$s</xliff:g> रेट किया गया है.\nइस कार्यक्रम को देखने के लिए, Right दबाएं और अपना पिन डालें."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"इस चैनल को देखने के लिए, डिफ़ॉल्ट लाइव टीवी ऐप का उपयोग करें."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"इस कार्यक्रम को देखने के लिए, डिफ़ॉल्ट लाइव टीवी ऐप का उपयोग करें."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"इस कार्यक्रम को रेट नहीं किया गया है.\nइसे देखने के लिए, डिफ़ॉल्ट Live TV ऐप्लिकेशन का उपयोग करें."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"इस कार्यक्रम को <xliff:g id="RATING">%1$s</xliff:g> रेट किया गया है.\nइस कार्यक्रम को देखने के लिए, डिफ़ॉल्ट लाइव टीवी ऐप का उपयोग करें."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"यह कार्यक्रम बंद कर दिया गया है"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"इस कार्यक्रम को रेट नहीं किया गया है"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"इस कार्यक्रम को <xliff:g id="RATING">%1$s</xliff:g> रेट किया गया है"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"केवल ऑडियो"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"कमज़ोर सिग्नल"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"टीवी मेनू ऐक्‍सेस करने के लिए "<b>"चुनें"</b>" दबाएं."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"कोई टीवी इनपुट नहीं मिला"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"टीवी इनपुट नहीं मिल पा रहा है"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP समर्थित नहीं है"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"कोई उपलब्ध इनपुट नहीं है जिसे PIP के साथ दिखाया जा सके"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ट्यूनर प्रकार उपयुक्‍त नहीं है. कृपया ट्यूनर प्रकार टीवी इनपुट के लिए Live TV ऐप लॉन्‍च करें."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ट्यून विफल रहा"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"यह कार्रवाई प्रबंधित करने के लिए कोई ऐप नहीं मिला."</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d रिकॉर्डिंग शेड्यूल की गईं</item>
       <item quantity="other">%1$d रिकॉर्डिंग शेड्यूल की गईं</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"रिकॉर्डिंग रद्द करें"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"रिकॉर्डिंग बंद करें"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"देखें"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"शुरू से चलाएं"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"चलाना फिर शुरू करें"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"जब एक ही समय पर कई सारे कार्यक्रम रिकॉर्ड करने हों, तो केवल उच्च प्राथमिकता वाले कार्यक्रम रिकॉर्ड किए जाएंगे."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"सहेजें"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"एक बार की रिकॉर्डिंग को उच्च प्राथमिकता दी जाती है"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"रद्द करें"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"रद्द करें"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"भूल जाएं"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"रोकें"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"रिकॉर्डिंग शेड्यूल देखें"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"यह एक ही कार्यक्रम"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"उसके बजाय इसे रिकॉर्ड करें"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"यह रिकॉर्डिंग रद्द करें"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"अभी देखें"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"रिकॉर्डिंग हटाएं…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"रिकॉर्ड करने योग्य"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"रिकॉर्डिंग शेड्यूल की गई"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"रिकॉर्डिंग संबंधी विरोध"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"रिकॉर्ड हो रहा है"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"रिकॉर्डिंग विफल रही"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"रिकॉर्डिंग शेड्यूल बनाने के लिए कार्यक्रम पढ़े जा रहे हैं"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"प्रोग्राम पढ़े जा रहे हैं"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"कार्यक्रम पढ़े जा रहे हैं"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"हाल ही की रिकॉर्डिंग देखें"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> की रिकॉर्डिंग अधूरी है."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> और <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> की रिकॉर्डिंग अधूरी है."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> और <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> की रिकॉर्डिंग अधूरी है."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"पर्याप्त जगह नहीं होने के कारण <xliff:g id="PROGRAMNAME">%1$s</xliff:g> की रिकॉर्डिंग पूरी नहीं हुई."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"पर्याप्त जगह नहीं होने के कारण <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> और <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> की रिकॉर्डिंग पूरी नहीं हुई."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"पर्याप्त जगह नहीं होने के कारण <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> और <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> की रिकॉर्डिंग पूरी नहीं हुई."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR को अधिक जगह की आवश्यकता है"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"आप DVR से प्रोग्राम रिकॉर्ड कर पाएंगे. हालांकि इस समय आपके डिवाइस पर DVR के काम करने के लिए पर्याप्त जगह नहीं है. कृपया एक बाहरी डिवाइस कनेक्ट करें जिसमें <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB या उससे अधिक जगह हो और उसे डिवाइस जगह के रूप में फ़ॉर्मेट करने के चरणों का अनुसरण करें."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"आप DVR से प्रोग्राम रिकॉर्ड कर पाएंगे. हालांकि इस समय आपके डिवाइस पर DVR के काम करने के लिए पर्याप्त जगह नहीं है. कृपया एक बाहरी डिवाइस कनेक्ट करें जिसमें <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB या उससे अधिक जगह हो और उसे डिवाइस जगह के रूप में फ़ॉर्मेट करने के चरणों का अनुसरण करें."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"पर्याप्‍त जगह नहीं है"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"इस कार्यक्रम को रिकॉर्ड नहीं किया जाएगा क्योंकि पर्याप्त जगह उपलब्ध नहीं है. कुछ मौजूदा रिकॉर्डिंग हटाकर देखें."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"जगह मिल नहीं रही है"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR द्वारा उपयोग की गई कुछ जगह मिल नहीं रही है. कृपया DVR को दोबारा सक्षम करने से पहले अपनी उपयोग की हुई बाहरी डिस्क कनेक्ट करें. वैकल्पिक रूप से, यदि जगह अब उपलब्ध नहीं है तो आप उसे भूल जाना चुन सकते हैं."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"जगह को भूल जाएं?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"आपकी रिकॉर्ड की हुई सभी सामग्री और शेड्यूल खो जाएंगे."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"रिकॉर्डिंग बंद करें?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"रिकॉर्ड की गई सामग्री सहेज ली जाएगी."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> की रिकॉर्डिंग रोक दी जाएगी क्योंकि यह इस प्रोग्राम का विरोध करता है. रिकॉर्ड की गई सामग्री सहेज ली जाएगी."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"रिकॉर्डिंग शेड्यूल की गई लेकिन विरोध मौजूद हैं"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"रिकॉर्डिंग शुरू हो गई है लेकिन उसमें विरोध मौजूद हैं"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> रिकॉर्ड किया जाएगा."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"इसी कार्यक्रम को <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> बजे रिकॉर्ड करने के लिए पहले ही शेड्यूल किया जा चुका है."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"पहले ही रिकॉर्ड हो चुका है"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"यह कार्यक्रम पहले ही रिकॉर्ड हो चुका है. वह DVR लाइब्रेरी में उपलब्ध है."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"सीरीज़ रिकॉर्डिंग शेड्यूल की गई"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं. अन्य शेड्यूल से विरोधों के कारण उनमें से <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> को रिकॉर्ड नहीं किया जाएगा.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं. अन्य शेड्यूल से विरोधों के कारण उनमें से <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> को रिकॉर्ड नहीं किया जाएगा.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं. अन्य शेड्यूल और दूसरे सीरीज़ के एपिसोड से विरोधों के कारण इस सीरीज़ और अन्य सीरीज़ के <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> एपिसोड रिकॉर्ड नहीं किए जाएंगे.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं. अन्य शेड्यूल और दूसरे सीरीज़ के एपिसोड से विरोधों के कारण इस सीरीज़ और अन्य सीरीज़ के <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> एपिसोड रिकॉर्ड नहीं किए जाएंगे.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं. इस सीरीज़ से विरोधों के कारण अन्य सीरीज़ का 1 एपिसोड रिकॉर्ड नहीं किया जाएगा.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं. इस सीरीज़ से विरोधों के कारण अन्य सीरीज़ का 1 एपिसोड रिकॉर्ड नहीं किया जाएगा.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं. इस सीरीज़ से विरोधों के कारण अन्य सीरीज़ के <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> एपिसोड रिकॉर्ड नहीं किए जाएंगे.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> के लिए <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रिकॉर्डिंग शेड्यूल कर दी गई हैं. इस सीरीज़ से विरोधों के कारण अन्य सीरीज़ के <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> एपिसोड रिकॉर्ड नहीं किए जाएंगे.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"रिकॉर्ड किया गया प्रोग्राम नहीं मिला."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"संबंधित रिकॉर्डिंग"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(कोई कार्यक्रम वर्णन नहीं)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d रिकॉर्डिंग</item>
       <item quantity="other">%1$d रिकॉर्डिंग</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"श्रृंखला की रिकॉर्डिंग रोकें?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"रिकॉर्ड किए गए एपिसोड DVR लाइब्रेरी में उपलब्ध रहेंगे."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"रोकें"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"इस समय कोई भी एपिसोड प्रसारित नहीं हो रहा है."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"कोई भी एपिसोड उपलब्ध नहीं है.\nएपिसोड उपलब्ध होने पर उन्हें रिकॉर्ड कर लिया जाएगा."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d मिनट)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> आज"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> कल"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"स्कोर"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"रिकॉर्ड किए गए कार्यक्रम"</string>
 </resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 596a3f9..a4f000e 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Kontrole reprodukcije"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Nedavni kanali"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanali"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV opcije"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opcije PIP-a"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Kontrole reprodukcije nisu dostupne za ovaj kanal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Reprodukcija ili pauziranje"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Brzo unaprijed"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Titlovi"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Način prikaza"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Uključeno"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Isključeno"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multiaudio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Više kanala"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Postavke"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Izvor"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Zamijeni"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Uključeno"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Isključeno"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Zvuk"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Glavni"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Prozor PIP-a"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Raspored"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Pri dnu desno"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Pri vrhu desno"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Pri vrhu lijevo"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Pri dnu lijevo"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Jedno uz drugo"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Veličina"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Velik"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Malen"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Izvor ulaza"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Nema podataka o programu"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Nema informacija"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blokirani kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Nepoznati jezik"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Nepoznati jezik"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Titlovi %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Titlovi"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Isključeno"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Prilagodi format"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Grupiraj po"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Program je blokiran"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ovaj je program neocijenjen"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Program ima ocjenu <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Ulaz ne podržava automatsko pretraživanje"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Nije moguće pokretanje automatskog pretraživanja za \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -93,7 +75,6 @@
       <item quantity="other">Dodano je %1$d kanala</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Kanali nisu dodani"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tražilo"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Roditeljski nadzor"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Uključeno"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Isključeno"</string>
@@ -109,6 +90,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Ostale zemlje"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ništa"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ništa"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Neocijenjeno"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokiraj neocijenjene programe"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ništa"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Visoka ograničenja"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Srednja ograničenja"</string>
@@ -125,6 +108,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Unesite PIN da biste gledali ovaj kanal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Unesite PIN da biste gledali ovaj program"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Ovaj program ima ocjenu <xliff:g id="RATING">%1$s</xliff:g>. Da biste ga gledali, unesite PIN"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ovaj je program neocijenjen. Da biste ga gledali, unesite PIN"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Unesite PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Da biste postavili roditeljski nadzor, stvorite PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Unesite novi PIN"</string>
@@ -137,22 +121,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN je pogrešan. Pokušajte ponovno."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Pokušaj ponovo, PIN se ne podudara"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Unesite svoj poštanski broj."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Na temelju poštanskog broja aplikacija TV kanali uživo pružit će vam potpun programski vodič za TV kanale."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Unesite svoj poštanski broj"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Poštanski broj nije važeći"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Postavke"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Prilagodite popis kanala"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Odaberite kanale za programski vodič"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Izvori kanala"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Dostupni su novi kanali"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Roditeljski nadzor"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Vremenski pomak"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Snimajte tijekom gledanja da biste mogli pauzirati ili premotavati emisije uživo.\nUpozorenje: time se može skratiti trajanje interne pohrane zbog njezine intenzivne upotrebe."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licence otvorenog izvornog koda"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licence otvorenog izvornog koda"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Pošaljite povratne informacije"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Verzija"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Da biste gledali ovaj kanal, pritisnite desno pa unesite PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Da biste gledali ovaj program, pritisnite desno pa unesite PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ovaj je program neocijenjen.\nDa biste ga gledali, pritisnite desno i unesite PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Ovaj program ima ocjenu <xliff:g id="RATING">%1$s</xliff:g>.\nDa biste ga gledali, pritisnite desni gumb pa unesite PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Da biste gledali ovaj kanal, upotrijebite zadanu aplikaciju za TV uživo."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Da biste gledali ovaj program, upotrijebite zadanu aplikaciju za TV uživo."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ovaj je program neocijenjen.\nDa biste ga gledali, upotrijebite zadanu aplikaciju za TV uživo."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Ovaj program ima ocjenu <xliff:g id="RATING">%1$s</xliff:g>.\nDa biste ga gledali, upotrijebite zadanu aplikaciju za TV uživo."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Program je blokiran"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ovaj je program neocijenjen"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Program ima ocjenu <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Samo zvuk"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Slab signal"</string>
@@ -185,8 +178,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Pritisnite ODABERITE"</b>" da biste pristupili izborniku TV-a."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"TV ulaz nije pronađen"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV ulaz nije pronađen"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP nije podržan"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Nema dostupnog ulaza koji se može prikazati putem PIP-a"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Vrsta prijemnika nije prikladna. Pokrenite aplikaciju Kanali uživo ako želite koristiti prijemnik kao TV ulaz."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Traženje kanala nije uspjelo"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Nije pronađena nijedna aplikacija koja može provesti tu radnju."</string>
@@ -235,6 +226,8 @@
       <item quantity="few">%1$d snimanja zakazana</item>
       <item quantity="other">%1$d snimanja zakazano</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Otkaži snimanje"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Zaustavi snimanje"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Gledaj"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Reproduciraj od početka"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Nastavi reprodukciju"</string>
@@ -268,9 +261,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Kada će se se istovremeno trebati snimati previše emisija, snimit će se samo one s najvišim prioritetom."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Spremi"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Jednokratna snimanja imaju najviši prioritet"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Odustani"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Odustani"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Zaboravi"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Zaustavi"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Prikaz rasporeda snimanja"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Samo jedna epizoda"</string>
@@ -280,25 +270,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Snimi ovo"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Otkaži snimanje"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Pogledajte odmah"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Brisanje snimki…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Snimanje moguće"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Snimanje programirano"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Sukob rasporeda snimanja"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Snimanje"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Snimanje nije uspjelo"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Čitanje emisija za izradu rasporeda snimanja"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Čitanje emisija"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Čitanje emisija"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Prikaži nedavne snimke"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Snimka sadržaja <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nije dovršena."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Snimke sadržaja <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> i <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nisu dovršene."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Snimke sadržaja <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> i <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nisu dovršene."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Snimanje sadržaja <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nije dovršeno jer nema dovoljno mjesta u pohrani."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Snimanje sadržaja <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> i <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nije dovršeno jer nema dovoljno mjesta u pohrani."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Snimanje sadržaja <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> i <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nije dovršeno jer nema dovoljno mjesta u pohrani."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR treba više prostora za pohranu"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Moći ćete snimati programe DVR-om. No na vašem uređaju trenutačno nema dovoljno prostora za pohranu da bi DVR funkcionirao. Priključite vanjski disk od najmanje <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB i formatirajte ga kao pohranu uređaja prema uputama."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Moći ćete snimati programe DVR-om. No na vašem uređaju trenutačno nema dovoljno prostora za pohranu da bi DVR funkcionirao. Priključite vanjski disk od najmanje <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB i formatirajte ga kao pohranu uređaja prema uputama."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Nema dovoljno prostora za pohranu"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Emisija se neće snimiti jer nema dovoljno prostora za pohranu. Izbrišite neke snimljene emisije."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Pohrana nedostaje"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Nedostaje dio pohrane kojom se koristi DVR. Da biste ponovo omogućili DVR, povežite ga s vanjskim diskom koji ste upotrebljavali prethodno. Ako ta pohrana više nije dostupna, možete odabrati da je uređaj zaboravi."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Zaboraviti pohranu?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Izgubit ćete sve snimljene sadržaje i programirana snimanja."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Želite li zaustaviti snimanje?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Snimljeni će se sadržaj spremiti."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Snimanje sadržaja <xliff:g id="PROGRAMNAME">%1$s</xliff:g> zaustavit će se zbog sukoba s ovim programom. Snimljeni sadržaj ostat će spremljen."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Snimanje je programirano, ali ima sukoba"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Snimanje je započelo, ali ima sukoba"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Snimit će se <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -317,17 +310,34 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Snimanje tog programa već je programirano za <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Već snimljeno"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Taj je program već snimljen. Dostupan je u zbirci DVR-a."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Snimanje serije je zakazano"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanje zakazano je za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanja zakazana su za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanja zakazano je za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanje zakazano je za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> od njih neće se snimiti zbog sukoba.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanja zakazana su za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> od njih neće se snimiti zbog sukoba.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanja zakazano je za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> od njih neće se snimiti zbog sukoba.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> snimanje zakazano je za seriju <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizoda/e te serije i druge serije neće se snimiti zbog sukoba.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> snimanja zakazana su za seriju <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizoda/e te serije i druge serije neće se snimiti zbog sukoba.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> snimanja zakazano je za seriju <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizoda/e te serije i druge serije neće se snimiti zbog sukoba.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanje zakazano je za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 epizoda neke druge serije neće se snimiti zbog sukoba.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanja zakazana su za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 epizoda neke druge serije neće se snimiti zbog sukoba.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> snimanja zakazano je za seriju <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 epizoda neke druge serije neće se snimiti zbog sukoba.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> snimanje zakazano je za seriju <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizoda/e neke druge serije neće se snimiti zbog sukoba.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> snimanja zakazana su za seriju <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizoda/e neke druge serije neće se snimiti zbog sukoba.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> snimanja zakazano je za seriju <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizoda/e neke druge serije neće se snimiti zbog sukoba.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Snimljeni program nije pronađen."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Povezane snimke"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Nema opisa programa)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d snimka</item>
       <item quantity="few">%1$d snimke</item>
@@ -349,6 +359,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Želite li zaustaviti snimanje serije?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Snimljene epizode ostat će dostupne u zbirci DVR-a."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Zaustavi"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Trenutačno se ne emitira nijedna epizoda."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nije dostupna nijedna epizoda.\nEpizode će se snimiti kada budu dostupne."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minuta)</item>
@@ -361,4 +372,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> danas"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> sutra"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Rezultat"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Snimljene emisije"</string>
 </resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index d007a13..f28b314 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"monó"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"sztereó"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Lejátszásvezérlők"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Legutóbbiak"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Csatornák"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Tv beállításai"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-beállítások"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"A lejátszási vezérlők nem érhetők el ennél a csatornánál"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Lejátszás vagy szüneteltetés"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Előretekerés"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Feliratok"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Megjelenítés"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Bekapcsolva"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Kikapcsolva"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Több hangsáv"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"További csatornák"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Beállítások"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Forrás"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Csere"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Bekapcsolva"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Kikapcsolva"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Hang"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Elsődleges"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-ablak"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Elrendezés"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Lent jobbra"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Fent jobbra"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Fent balra"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Lent balra"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Egymás mellett"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Méret"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Nagy"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Kicsi"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Bemeneti forrás"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenna/kábel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Nincsenek műsorinformációk"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Nincs információ."</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Letiltott csatorna"</string>
-    <string name="default_language" msgid="4122326459624337928">"Ismeretlen nyelv"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Ismeretlen nyelv"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Feliratok (%1$d)"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Feliratok"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Kikapcsolva"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Személyre szabás"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Csoportosítás"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"A műsor le van tiltva."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ez a műsor nem rendelkezik besorolással"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"A műsor besorolása: <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"A bemenet nem támogatja az automatikus keresést"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Nem lehet elindítani a(z) „<xliff:g id="TV_INPUT">%s</xliff:g>” automatikus keresését"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d csatorna hozzáadva</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Nincs csatorna hozzáadva"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Szülői felügyelet"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Bekapcsolva"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Kikapcsolva"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Más országok"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Nincs"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Nincs"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Nincs besorolás"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Nem besorolt műsorok letiltása"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Nincs"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Magas korlátozások"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Közepes korlátozások"</string>
@@ -124,33 +107,43 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"A csatorna megtekintéséhez PIN-kód szükséges"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"A műsor megtekintéséhez PIN-kód szükséges"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"A műsor besorolása: <xliff:g id="RATING">%1$s</xliff:g>. A megtekintéséhez adja meg PIN-kódját."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ez a műsor nem rendelkezik besorolással. Adja meg PIN-kódját a műsor megtekintéséhez"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PIN-kód megadása"</string>
-    <string name="pin_enter_create_pin" msgid="3385754356793309946">"Szülői felügyelet beállításához hozzon létre egy PIN kódot."</string>
+    <string name="pin_enter_create_pin" msgid="3385754356793309946">"Szülői felügyelet beállításához hozzon létre egy PIN-kódot."</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Új PIN-kód megadása"</string>
     <string name="pin_enter_again" msgid="2618999754723090427">"PIN-kód megerősítése"</string>
-    <string name="pin_enter_old_pin" msgid="4588282612931041919">"Adja meg a jelenlegi PIN kódot"</string>
+    <string name="pin_enter_old_pin" msgid="4588282612931041919">"Adja meg a jelenlegi PIN-kódot"</string>
     <plurals name="pin_enter_countdown" formatted="false" msgid="3415233538538544309">
       <item quantity="other">Helytelen PIN-kódot adott meg ötször egymás után.\nPróbálja újra <xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> másodperc múlva.</item>
       <item quantity="one">Helytelen PIN-kódot adott meg ötször egymás után.\nPróbálja újra <xliff:g id="REMAINING_SECONDS_0">%1$d</xliff:g> másodperc múlva.</item>
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"A PIN-kód helytelen, próbálja újra."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"A PIN-kód nem egyezik, próbálja újra"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Irányítószám megadása"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Az Élő Csatornák alkalmazás az irányítószám használatával megjeleníti a csatornák teljes tévéműsorát."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Adja meg irányítószámát"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Érvénytelen irányítószám"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Beállítások"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Csatornalista testreszabása"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Válasszon csatornákat a műsorfüzetbe"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Csatornaforrások"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Új csatornák állnak rendelkezésre"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Szülői felügyelet"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Időeltolás"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"A nézésük közben felveheti a műsorokat, így szüneteltetheti vagy visszatekerheti őket.\nFigyelmeztetés: A belső tárhely intenzív használata miatt ez a funkció csökkentheti a tárhely élettartamát."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Nyílt forráskódú licencek"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Nyílt forráskódú licencek"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Visszajelzés küldése"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Verzió"</string>
-    <string name="tvview_channel_locked" msgid="6486375335718400728">"A csatorna megtekintéséhez nyomja meg a jobbra gombot, majd adja meg a PIN kódot"</string>
-    <string name="tvview_content_locked" msgid="391823084917017730">"A műsor megtekintéséhez nyomja meg a jobbra gombot, majd adja meg a PIN kódot"</string>
-    <string name="tvview_content_locked_format" msgid="3741874636031338247">"A műsor besorolása: <xliff:g id="RATING">%1$s</xliff:g>.\nA megtekintéséhez nyomja meg a jobbra gombot, majd adja meg a PIN kódot."</string>
+    <string name="tvview_channel_locked" msgid="6486375335718400728">"A csatorna megtekintéséhez nyomja meg a jobbra gombot, majd adja meg a PIN-kódot"</string>
+    <string name="tvview_content_locked" msgid="391823084917017730">"A műsor megtekintéséhez nyomja meg a jobbra gombot, majd adja meg a PIN-kódot"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ez a műsor nem rendelkezik besorolással.\nA műsor megtekintéséhez nyomja meg a Jobb gombot, majd adja meg a PIN-kódot"</string>
+    <string name="tvview_content_locked_format" msgid="3741874636031338247">"A műsor besorolása: <xliff:g id="RATING">%1$s</xliff:g>.\nA megtekintéséhez nyomja meg a jobbra gombot, majd adja meg a PIN-kódot."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"A csatorna megtekintéséhez használja az alapértelmezett  „Live TV” alkalmazást."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"A program megtekintéséhez használja az alapértelmezett „Live TV” alkalmazást."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ez a műsor nem rendelkezik besorolással.\nA műsor megtekintéséhez használja az alapértelmezett „Live TV” alkalmazást."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"A program besorolása: <xliff:g id="RATING">%1$s</xliff:g>.\nA megtekintéséhez használja az alapértelmezett „Live TV” alkalmazást."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"A műsor le van tiltva"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ez a műsor nem rendelkezik besorolással"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"A műsor besorolása: <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Csak hang"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Gyenge jel"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Nyomja meg a KIVÁLASZTÁS"</b>" gombot a tévé menüjének eléréséhez."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nem található tévébemenet."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"A tévébemenet nem található."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"A kép a képben funkció nem támogatott."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Nincs elérhető bemeneti adás, amely megjeleníthető lenne a kép a képben (picture in picture, PIP) funkcióval."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"A tuner típusa nem megfelelő. Indítsa el a tévé bemeneti tunertípusának megfelelő Élő csatornák alkalmazást."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Tunerhiba"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Nincs megfelelő alkalmazás a művelet végrehajtásához."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d rögzítés beütemezve</item>
       <item quantity="one">%1$d rögzítés beütemezve</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Felvétel megszakítása"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Felvétel leállítása"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Megtekintés"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Lejátszás az elejétől"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Lejátszás folytatása"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Ha túl sok rögzítendő műsort állít be ugyanarra az időtartamra, kizárólag a magasabb prioritással rendelkezőket rögzíti a rendszer."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Mentés"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Az egyszeri rögzítések rendelkeznek a legmagasabb prioritással"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Mégse"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Mégse"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Elfelejt"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Leállítás"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Rögzítési ütemterv megtekintése"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Ezt az egy műsort"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Inkább ez legyen rögzítve"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"A rögzítés törlése"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Nézze meg most"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Felvételek törlése…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Felvehető"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"A felvétel beállítva"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Ütközés más felvétellel"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Rögzítés"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"A felvétel nem sikerült"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Műsorok beolvasása a rögzítési ütemterv kialakításához"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Műsorok beolvasása"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Műsorok beolvasása"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"A legutóbbi felvételek megtekintése"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"A(z) <xliff:g id="PROGRAMNAME">%1$s</xliff:g> felvétele megszakadt."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"A következők felvétele megszakadt: <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> és <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"A következők felvétele megszakadt: <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> és <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"A(z) <xliff:g id="PROGRAMNAME">%1$s</xliff:g> felvétele nem sikerült, mert nincs elég tárhely."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"A következők felvétele a kevés tárhely miatt nem sikerült: <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> és <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"A következők felvétele a kevés tárhely miatt nem sikerült: <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> és <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"A DVR számára több tárhely szükséges"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"A DVR segítségével műsorokat vehet fel. Azonban eszközén nincs elég szabad tárhely a DVR működéséhez. Csatlakoztasson egy legalább <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB tárhellyel rendelkező külső meghajtót, majd kövesse az utasításokat, hogy az eszköz tárhelyévé formázhassa."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"A DVR segítségével műsorokat vehet fel. Azonban eszközén nincs elég szabad tárhely a DVR működéséhez. Csatlakoztasson egy legalább <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB tárhellyel rendelkező külső meghajtót, majd kövesse az utasításokat, hogy az eszköz tárhelyévé formázhassa."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Nincs elegendő tárhely"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Ez a műsor nem lesz felvéve, mivel nincs elegendő tárhely. Próbáljon meg törölni néhány meglévő felvételt."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Hiányzó tárhely"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"A DVR által használt tárhely bizonyos része hiányzik. Kérjük, csatlakoztassa a korábban használt külső meghajtót a DVR ismételt engedélyezéséhez. Másik megoldásként megadhatja a rendszernek, hogy ne emlékezzen többé erre a tárhelyre, ha már nem áll a rendelkezésére."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"A rendszer ne emlékezzen többé erre a tárhelyre?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Az összes rögzített tartalom és ütemterv elvész."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Leállítja a rögzítést?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"A rögzített tartalmat elmenti a rendszer."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"A(z) <xliff:g id="PROGRAMNAME">%1$s</xliff:g> felvétele le fog állni, mert ütközik ezzel a programmal. A felvett tartalmat az alkalmazás menteni fogja."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"A rögzítést beállította, de az ütközik más műsorokkal"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"A rögzítés elindult, de az ütközik más műsorokkal"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"A(z) <xliff:g id="PROGRAMNAME">%1$s</xliff:g> rögzítve lesz."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Ugyanennek a műsornak a rögzítése már be van ütemezve a következő időpontban: <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Már készült róla felvétel"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Erről a műsorról már készült felvétel, amely a DVR könyvtárban található."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Sorozatfelvétel ütemezve"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Ütközés miatt a rendszer nem rögzít <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> felvételt.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Ütközés miatt a rendszer nem rögzíti a felvételt.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Ütközés miatt a rendszer <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizódot nem rögzít ebből, valamint más sorozatokból.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Ütközés miatt a rendszer <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> epizódot nem rögzít ebből, valamint más sorozatokból.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Ütközés miatt a rendszer 1 epizódot nem rögzít más sorozatokból.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Ütközés miatt a rendszer 1 epizódot nem rögzít más sorozatokból.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Ütközés miatt a rendszer <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> epizódot nem rögzít más sorozatokból.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> felvétel van ütemezve a következőhöz: <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Ütközés miatt a rendszer <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> epizódot nem rögzít más sorozatokból.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"A rögzített program nem található."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Kapcsolódó felvételek"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Nincs programleírás)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d felvétel</item>
       <item quantity="one">%1$d felvétel</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Leállítja a sorozat rögzítését?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"A rögzített részek továbbra is hozzáférhetők lesznek a DVR könyvtárban."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Leállítás"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Egyetlen epizódot sem közvetítenek jelenleg."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nincs rendelkezésre álló epizód.\nAz epizódok a megjelenésüket követően lesznek rögzítve."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d perc)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Ma: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Holnap: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Pontszám"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Felvett műsorok"</string>
 </resources>
diff --git a/res/values-hy-v23/strings.xml b/res/values-hy-rAM-v23/strings.xml
similarity index 100%
rename from res/values-hy-v23/strings.xml
rename to res/values-hy-rAM-v23/strings.xml
diff --git a/res/values-hy/arrays.xml b/res/values-hy-rAM/arrays.xml
similarity index 100%
rename from res/values-hy/arrays.xml
rename to res/values-hy-rAM/arrays.xml
diff --git a/res/values-hy/rating_system_strings.xml b/res/values-hy-rAM/rating_system_strings.xml
similarity index 100%
rename from res/values-hy/rating_system_strings.xml
rename to res/values-hy-rAM/rating_system_strings.xml
diff --git a/res/values-hy/strings.xml b/res/values-hy-rAM/strings.xml
similarity index 78%
rename from res/values-hy/strings.xml
rename to res/values-hy-rAM/strings.xml
index d10652e..a723a2a 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"մոնո"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ստերեո"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Նվագարկման կառավար"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Վերջինները"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Հեռուստաալիքներ"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Հեռ. ընտրանքներ"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP ընտրանքներ"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Նվագարկման կառավարներն այս ալիքում անհասանելի են"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Նվագարկել կամ դադարեցնել"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Արագ առաջանցում"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Փակ խորագրեր"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Ցուցադրման ռեժիմ"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Միացված է"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Անջատված է"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Բազմաուդիո"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Ավելացնել ալիքներ"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Կարգավորումներ"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Աղբյուր"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Փոխել"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Միացված է"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Անջատված է"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Ձայն"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Հիմնական"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP պատուհան"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Դասավորություն"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Ստորին աջ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Վերին աջ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Վերին ձախ"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Ստորին ձախ"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Կողք կողքի"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Չափը"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Մեծ"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Փոքր"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Աղբյուր"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Հեռուստացույց (ալեհավաք/մալուխ)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Ծրագրի մասին տեղեկություններ չկան"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Տեղեկություն չկա"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Ալիքն արգելափակված է:"</string>
-    <string name="default_language" msgid="4122326459624337928">"Անհայտ լեզու"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Անհայտ լեզու"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"%1$d ենթագրեր"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Փակ ենթագրեր"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Անջատված է"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Հարմարացնել ձևաչափը"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Խմբավորել"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Այս ծրագիրը արգելափակված է"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ծրագիրը գնահատված չէ"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Այս ծրագրի վարկանիշը <xliff:g id="RATING">%1$s</xliff:g> է"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Մուտքը ինքնասկանավարում չի աջակցում"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Չի հաջողվում սկսել «<xliff:g id="TV_INPUT">%s</xliff:g>»-ի ավտոմատ սկանավորումը"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">Ավելացվեց %1$d ալիք</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Ալիքներ չեն ավելացվել"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Ծնողական հսկում"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Միացված է"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Անջատված է"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Այլ երկրներ"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Չկա"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Չկա"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Չգնահատված"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Արգելափակել չգնահատված ծրագրերը"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Չկա"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Խիստ սահմանափակում"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Միջ. սահմանափակումներ"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Այս ալիքը դիտելու համար մուտքագրեք PIN-ը"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Այս ծրագիրը դիտելու համա մուտքագրեք PIN-ը"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Այս ծրագիրն ունի տարիքային սահմանափակում՝ <xliff:g id="RATING">%1$s</xliff:g>: Այն դիտելու համար մուտքագրեք PIN կոդը"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ծրագիրը գնահատված չէ։ Մուտքագրեք PIN-ը՝ այն դիտելու համար"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Մուտքագրեք ձեր PIN-ը"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Ծնողական վերահսկումը կարգավորելու համար PIN կոդ նախադրեք"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Մուտքագրեք նոր PIN"</string>
@@ -135,24 +119,33 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN-ը սխալ էր: Կրկին փորձեք:"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Փորձեք կրկին, PIN-ը չի համապատասխանում"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Մուտքագրեք փոստային դասիչը:"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Ուղիղ եթեր հավելվածը փոստային դասիչը կօգտագործի հեռուստաալիքների ամբողջական ցանկը տրամադրելու համար։"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Մուտքագրեք փոստային դասիչը"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Փոստային դասիչը սխալ է"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Կարգավորումներ"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Հարմարեցնել ալիքների ցանկը"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Ընտրեք ալիքներ հեռուստահաղորդումների ծրագրի համար"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Ալիքների աղբյուրներ"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Առկա են նոր ալիքներ"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Ծնողական վերահսկողություն"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Ժամանակի կառավար"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Ձայնագրեք դիտելիս և կկարողանաք կանգնեցնել կամ հետարկել ուղիղ եթերով հեռարձակվող հաղորդումները:\nԶգուշացում. սա կարող է նվազեցնել ներքին հիշողության օգտագործման ժամկետը, եթե ինտենսիվորեն օգտագործեք հիշողությունը:"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Բաց կոդով ծրագրակազմի արտոնագրեր"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Բաց կոդով ծրագրաշարի լիցենզիաներ"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Կարծիք հայտնել"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Տարբերակ"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Այս կապուղին դիտելու համար սեղմեք Աջ և մուտքագրեք ձեր PIN-ը"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Այս ծրագիրը դիտելու համար սեղմեք Աջ և մուտքագրեք ձեր PIN-ը"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ծրագիրը գնահատված չէ։\nԱյն դիտելու համար սեղմեք «Աջ» կոճակը և մուտքագրեք ձեր PIN-ը"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Այս ծրագրի վարկանիշը <xliff:g id="RATING">%1$s</xliff:g> է:\nԱյն դիտելու համար սեղմեք Աջ և մուտքագրեք PIN կոդը:"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Այս ալիքը դիտելու համար օգտագործեք Live TV կանխադրված հավելվածը:"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Այս հաղորդումը դիտելու համար օգտագործեք Live TV կանխադրված հավելվածը:"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ծրագիրը գնահատված չէ։\nԱյն դիտելու համար օգտագործեք կանխադրված «Ուղիղ եթեր» հավելվածը"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Այս հաղորդումը գնահատվել է որպես <xliff:g id="RATING">%1$s</xliff:g>:\nԱյս հաղորդումը դիտելու համար օգտագործեք Live TV կենդանի կանխադրված հավելվածը:"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Ծրագիրն արգելափակված է"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ծրագիրը գնահատված չէ"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Այս ծրագրի վարկանիշը <xliff:g id="RATING">%1$s</xliff:g> է"</string>
-    <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Միայն ձայն"</string>
+    <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Միայն աուդիո"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Թույլ ազդանշան"</string>
     <string name="tvview_msg_no_internet_connection" msgid="7655994401188888231">"Համացանցի կապակցում չկա"</string>
     <plurals name="tvview_msg_input_no_resource" formatted="false" msgid="8581894855153658823">
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"Հեռուստացույցի ընտրացանկից օգտվելու համար "<b>"սեղմեք ԸՆՏՐԵԼ"</b>":"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Հեռուստացույցի մուտք չի գտնվել"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Հեռուստացույցի մուտքը տեղադրված չէ"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP-ը չի աջակցվում"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP-ը ցուցադրելու համար աղբյուր չկա"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Կարգավորիչի մուտքը համապատասխան չէ: Գործարկեք «Ուղիղ եթեր» հավելվածը, եթե օգտագործում եք հեռուստացույցի մուտք:"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Կարգավորումը չհաջողվեց"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Այս գործողությունը կատարելու համար ոչ մի հավելված չի գտնվել"</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d recordings scheduled</item>
       <item quantity="other">Ծրագրավորվել է %1$d տեսագրություն</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Չեղարկել տեսագրումը"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Դադարեցնել տեսագրումը"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Դիտել"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Նվագարկել սկզբից"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Վերսկսել նվագարկումը"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Եթե միաժամանակ ծրագրավորված է չափազանց շատ ծրագրերի տեսագրում, ապա կտեսագրվեն միայն բարձր առաջնահերթություն ունեցող ծրագրերը:"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Պահել"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Միանգամյա տեսագրումն ունի ամենաբարձր առաջնահերթությունը"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Չեղարկել"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Չեղարկել"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Մոռանալ"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Դադար"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Դիտել տեսագրման ժամանակացույցը"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Միայն այս ծրագիրը"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Փոխարենը տեսագրել այս ծրագիրը"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Չեղարկել այս տեսագրումը"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Դիտել հիմա"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Ջնջել տեսագրությունները…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Հնարավոր է տեսագրել"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Տեսագրումը ծրագրավորված է"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Տեսագրման հակասություն"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Տեսագրում"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Չհաջողվեց տեսագրել"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Ծրագրերի ընթերցում՝ տեսագրության ժամանակացույցեր ստեղծելու համար"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Ծրագրերի ընթերցում"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Ծրագրերի ընթերցում"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Դիտել վերջին տեսագրությունները"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ծրագրի տեսագրումը չի ավարտվել:"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> և <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ծրագրերի տեսագրումը չի ավարտվել:"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> և <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ծրագրերի տեսագրումը չի ավարտվել:"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ծրագրի տեսագրումը չի ավարտվել, քանի որ հիշողությունը բավարար չէ:"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> և <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ծրագրերի տեսագրումը չի ավարտվել, քանի որ հիշողությունը բավարար չէ:"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> և <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ծրագրերի տեսագրումը չի ավարտվել, քանի որ հիշողությունը բավարար չէ:"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR-ին ավելի շատ հիշողություն է անհրաժեշտ"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Դուք կկարողանաք տեսագրել ծրագրեր DVR-ի օգնությամբ: Սակայն այս պահին ձեր սարքում DVR-ի աշխատանքի համար անհրաժեշտ բավականաչափ հիշողություն չկա: Միացեք առնվազն <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>ԳԲ հիշողություն ունեցող արտաքին սարք և հետևեք ցուցումներին՝ այն որպես սարքի հիշողություն ձևաչափելու համար:"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Դուք կկարողանաք տեսագրել ծրագրեր DVR-ի օգնությամբ: Սակայն այս պահին ձեր սարքում DVR-ի աշխատանքի համար անհրաժեշտ բավականաչափ հիշողություն չկա: Միացեք առնվազն <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>ԳԲ հիշողություն ունեցող արտաքին սարք և հետևեք ցուցումներին՝ այն որպես սարքի հիշողություն ձևաչափելու համար:"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Բավականաչափ հիշողություն չկա"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Այս ծրագիրը չի տեսագրվի բավականաչափ հիշողություն բացակայության պատճառով: Փորձեք ջնջել առկա տեսագրություններից մի քանիսը:"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Հիշողությունն անհասանելի է"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR-ի կողմից օգտագործվող հիշողության մի մասն անհասանելի է: DVR-ը կրկին ակտիվացնելու համար միացրեք նախկինում օգտագործված արտաքին սարքը: Կարող եք նաև մոռանալ հիշողությունը, եթե այն այևս հասանելի չէ:"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Մոռանա՞լ հիշողությունը:"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Ձեր տեսագրած ամբողջ բովանդակությունը և ժամանակացույցները չեն պահվի:"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Դադարեցնե՞լ տեսագրումը:"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Տեսագրված բովանդակությունը կպահվի:"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ծրագրի տեսագրումը կդադարեցվի, քանի որ այն ունի հակասություններ այս ծրագրի հետ: Արդեն իսկ տեսագրված բովանդակությունը կպահվի:"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Տեսագրումը ծրագրավորվեց, սակայն այն հակասություններ ունի"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Տեսագրումը սկսվել է, սակայն որոշ հակասություններ ունի"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ծրագիրը կտեսագրվի:"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Միևնույն ծրագրի տեսագրումն արդեն ծրագրավորվել է <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>-ին:"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Արդեն տեսագրվել է"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Այս ծրագիրն արդեն տեսագրվել է: Այն հասանելի է DVR դարանում:"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Սերիալի տեսագրումը ծրագրավորված է"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>-ի համար ծրագրավորված է <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> տեսագրում:</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> of them will not be recorded due to conflicts.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>-ի համար ծրագրավորված է <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> տեսագրում: Այդ տեսագրումներից <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>-ը հակասությունների պատճառով չեն կատարվի:</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g>-ի համար ծրագրավորված է <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> տեսագրում: Այս սերիալի <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> դրվագներ և մյուս սերիալը հակասությունների պատճառով չեն տեսագրվի:</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>-ի համար ծրագրավորված է <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> տեսագրում: Մյուս սերիալի 1 դրվագ հակասությունների պատճառով չի տեսագրվի:</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g>-ի համար ծրագրավորված է <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> տեսագրում: Մյուս սերիալի <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> դրվագներ հակասությունների պատճառով չեն տեսագրվի:</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Տեսագրված ծրագիրը չի գտնվել:"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Առնչվող տեսագրություններ"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Ծրագիրը նկարագրություն չունի)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d recordings</item>
       <item quantity="other">%1$d տեսագրություն</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Դադարեցնե՞լ սերիալի տեսագրումը:"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Տեսագրված դրվագները հասանելի կմնան միայն DVR դարանում:"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Դադար"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Այս պահին եթեր հեռարձակվող դրվագներ չկան:"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Հասանելի դրվագներ չկան:\nԴրանք կտեսագրվեն հասանելի դառնալուց հետո:"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minutes)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Այսօր, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Վաղը, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Գնահատական"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Տեսագրած ծրագրեր"</string>
 </resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 662cfc8..33cca96 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Kontrol pemutar"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Saluran terkini"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Saluran"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opsi TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opsi PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Kontrol Play tidak tersedia untuk saluran ini"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Putar atau jeda"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Maju cepat"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Teks"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Mode tayang"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Aktif"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Nonaktif"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Dapatkan saluran lain"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Setelan"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Sumber"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Tukar"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Aktif"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Nonaktif"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Suara"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Utama"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Jendela PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Tata letak"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Kanan bawah"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Kanan atas"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Kiri atas"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Kiri bawah"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Berdampingan"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Ukuran"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Besar"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Kecil"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Sumber masukan"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Tidak ada informasi program"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Tidak ada informasi"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Saluran yang diblokir"</string>
-    <string name="default_language" msgid="4122326459624337928">"Bahasa tidak dikenal"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Bahasa tidak dikenal"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtitel, CC %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Teks"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Nonaktif"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Sesuaikan format"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Kelompokkan menurut"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Program ini diblokir"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Program ini tidak memiliki nilai"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Program ini diberi rating <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Masukan tidak mendukung pemindaian otomatis"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Tidak dapat memulai pemindaian otomatis untuk \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d saluran ditambahkan</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Tidak ditambahkan saluran"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Kontrol induk"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Aktif"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Nonaktif"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Negara lain"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Tidak ada"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Tidak ada"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Tanpa nilai"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokir program tanpa nilai"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Tidak ada"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Pembatasan tinggi"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Pembatasan menengah"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Masukkan PIN untuk menonton saluran ini"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Masukkan PIN untuk menonton program ini"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Program ini memiliki rating <xliff:g id="RATING">%1$s</xliff:g>. Masukkan PIN untuk menonton program ini"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Program ini tidak memiliki nilai. Masukkan PIN untuk menonton program ini"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Masukkan PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Untuk menyetel kontrol induk, buat PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Masukkan PIN baru"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN salah. Coba lagi."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Pin tidak cocok, coba lagi"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Memasukkan Kode Pos"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Aplikasi Live TV akan menggunakan Kode Pos untuk memberikan panduan program lengkap bagi saluran TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Masukkan Kode Pos"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Kode ZIP Tidak Valid"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Setelan"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Sesuaikan daftar saluran"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Pilih saluran untuk panduan program"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Sumber saluran"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Tersedia saluran baru"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Kontrol induk"</string>
-    <string name="settings_menu_licenses" msgid="1257646083838406103">"Lisensi sumber terbuka"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Lisensi sumber terbuka"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Pergantian waktu"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Rekam sambil menonton sehingga Anda dapat menjeda atau memutar ulang program live.\nPeringatan: Tindakan ini menggunakan penyimpanan secara intensif sehingga dapat mengurangi masa pakai penyimpanan internal."</string>
+    <string name="settings_menu_licenses" msgid="1257646083838406103">"Lisensi open source"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Kirim masukan"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versi"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Untuk menonton saluran ini, tekan Kanan dan masukkan PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Untuk menonton program ini, tekan Kanan dan masukkan PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Program ini tidak memiliki nilai.\nUntuk menonton program ini, tekan Kanan lalu masukkan PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Program ini diberi rating <xliff:g id="RATING">%1$s</xliff:g>.\nUntuk menonton program ini, tekan Panah Kanan dan masukkan PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Untuk menonton saluran ini, gunakan aplikasi TV Siaran Langsung default."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Untuk menonton program ini, gunakan aplikasi TV Siaran Langsung default."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Program ini tidak memiliki nilai.\nUntuk menonton program ini, gunakan aplikasi TV Siaran Langsung default."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Program ini memiliki rating <xliff:g id="RATING">%1$s</xliff:g>.\nUntuk menonton program ini, gunakan aplikasi TV Siaran Langsung default."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Program diblokir"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Program ini tidak memiliki nilai"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Program ini diberi rating <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audio saja"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Sinyal lemah"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Tekan PILIH"</b>" untuk mengakses menu TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Tidak ditemukan masukan TV"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Tidak dapat menemukan masukan TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP tidak didukung"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Tidak tersedia masukan yang dapat ditampilkan dengan PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Jenis tuner tidak cocok. Luncurkan aplikasi Saluran Siaran Langsung untuk masukan TV yang sesuai dengan jenis tuner"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Penalaan gagal"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Tidak ditemukan aplikasi untuk menangani tindakan ini."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d jadwal rekaman</item>
       <item quantity="one">%1$d jadwal rekaman</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Batalkan rekaman"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Berhenti merekam"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Tonton"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Putar dari awal"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Lanjutkan pemutaran"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Jika terlalu banyak program yang akan direkam secara bersamaan, hanya program dengan prioritas lebih tinggi yang akan direkam."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Simpan"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Perekaman satu kali memiliki prioritas tertinggi"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Batal"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Batal"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Lupakan"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Berhenti"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Lihat jadwal rekaman"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Program tunggal ini"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Rekam yang ini saja"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Batalkan rekaman ini"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Tonton sekarang"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Hapus rekaman…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Dapat direkam"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Perekaman dijadwalkan"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Perekaman bentrok"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Merekam"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Rekaman gagal"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Membaca program untuk membuat jadwal rekaman"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Membaca program"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Membaca program"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Lihat rekaman baru-baru ini"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Rekaman <xliff:g id="PROGRAMNAME">%1$s</xliff:g> tidak selesai."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Rekaman <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> dan <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> tidak selesai."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Rekaman <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, dan <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> tidak selesai."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Rekaman <xliff:g id="PROGRAMNAME">%1$s</xliff:g> tidak selesai karena penyimpanan tidak mencukupi."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Rekaman <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> dan <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> tidak selesai karena penyimpanan tidak mencukupi."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Rekaman <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, dan <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> tidak selesai karena penyimpanan tidak mencukupi."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR memerlukan penyimpanan ekstra"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Anda akan dapat merekam program dengan DVR. Namun, saat ini penyimpanan pada perangkat tidak cukup untuk menjalankan DVR. Hubungkan drive eksternal berukuran <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB atau lebih besar dan ikuti langkah untuk memformat drive tersebut sebagai perangkat penyimpanan."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Anda akan dapat merekam program dengan DVR. Namun, saat ini penyimpanan pada perangkat tidak cukup untuk menjalankan DVR. Hubungkan drive eksternal berukuran <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB atau lebih besar dan ikuti langkah untuk memformat drive tersebut sebagai perangkat penyimpanan."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Penyimpanan tidak cukup"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Program ini tidak akan direkam karena penyimpanan tidak cukup. Coba menghapus beberapa rekaman yang ada."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Penyimpanan tidak ada"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Beberapa penyimpanan yang digunakan oleh DVR tidak ada. Hubungkan drive eksternal yang sebelumnya digunakan untuk kembali mengaktifkan DVR. Atau, Anda dapat memilih untuk melupakan penyimpanan jika sudah tidak tersedia."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Lupakan penyimpanan?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Semua konten dan jadwal yang direkam akan hilang."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Berhenti merekam?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Konten yang direkam akan disimpan."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Perekaman <xliff:g id="PROGRAMNAME">%1$s</xliff:g> akan dihentikan karena bentrok dengan program ini. Konten yang direkam akan disimpan."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Rekaman telah dijadwalkan, tapi jadwalnya bentrok"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Rekaman telah dimulai, namun jadwalnya bentrok"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> akan direkam."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Program yang sama telah dijadwalkan untuk direkam pukul <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Sudah direkam"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Program ini telah direkam. Rekaman ada di pustaka DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Perekaman serial dijadwalkan"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> rekaman tersebut tidak akan direkam karena jadwalnya bentrok.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Rekaman tersebut tidak akan direkam karena jadwalnya bentrok.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episode seri ini dan seri lainnya tidak akan direkam karena jadwalnya bentrok.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episode seri ini dan seri lainnya tidak akan direkam karena jadwalnya bentrok.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episode seri lainnya tidak akan direkam karena jadwalnya bentrok.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 episode seri lainnya tidak akan direkam karena jadwalnya bentrok.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episode seri lainnya tidak akan direkam karena jadwalnya bentrok.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rekaman telah dijadwalkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episode seri lainnya tidak akan direkam karena jadwalnya bentrok.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Tidak ditemukan program yang direkam."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Rekaman terkait"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Tidak ada deskripsi program)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d rekaman</item>
       <item quantity="one">%1$d rekaman</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Hentikan rekaman seri?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Episode yang direkam akan tetap tersedia di pustaka DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Hentikan"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Tidak ada episode tayang sekarang."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Tidak ada episode yang tersedia.\nEpisode akan direkam setelah tersedia."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d menit)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> hari ini"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> besok"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Skor"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Program yang Direkam"</string>
 </resources>
diff --git a/res/values-is-v23/strings.xml b/res/values-is-rIS-v23/strings.xml
similarity index 100%
rename from res/values-is-v23/strings.xml
rename to res/values-is-rIS-v23/strings.xml
diff --git a/res/values-is/arrays.xml b/res/values-is-rIS/arrays.xml
similarity index 100%
rename from res/values-is/arrays.xml
rename to res/values-is-rIS/arrays.xml
diff --git a/res/values-is/rating_system_strings.xml b/res/values-is-rIS/rating_system_strings.xml
similarity index 100%
rename from res/values-is/rating_system_strings.xml
rename to res/values-is-rIS/rating_system_strings.xml
diff --git a/res/values-is/strings.xml b/res/values-is-rIS/strings.xml
similarity index 78%
rename from res/values-is/strings.xml
rename to res/values-is-rIS/strings.xml
index 6111b57..99e8459 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"einóma"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"víðóma"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Spilunarstýringar"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Nýlegar rásir"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Rásir"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Sjónvarpskostir"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Innfelld mynd"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Spilunarstýringar eru ekki í boði fyrir þessa rás"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Spila eða gera hlé"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Spóla áfram"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Skjátextar"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Birtingarstill."</string>
     <string name="options_item_pip" msgid="3951350386626879645">"Innfelld mynd"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Kveikt"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Slökkt"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-Audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Fá fleiri rásir"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Stillingar"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Inntak"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Víxla"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Kveikt"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Slökkt"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Hljóð"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Aðalgluggi"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Innfelling"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Útlit"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Neðst til hægri"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Efst til hægri"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Efst til vinstri"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Neðst til vinstri"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Hlið við hlið"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Stærð"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Stór"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Lítil"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Inntak"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Sjónvarp (loftnet/kapall)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Engar dagskrárupplýsingar"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Engar upplýsingar"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Læst rás"</string>
-    <string name="default_language" msgid="4122326459624337928">"Óþekkt tungumál"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Óþekkt tungumál"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Skjátexti %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Skjátextar"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Slökkt"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Sérstilla snið"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"Staðalgæði"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Flokka eftir"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Þessi dagskrárliður er læstur"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Þessi þáttur er óflokkaður"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Þessi dagskrárliður er flokkaður sem <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Inntakið styður ekki sjálfvirka skönnun"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Ekki tókst að hefja sjálfvirka skönnun fyrir „<xliff:g id="TV_INPUT">%s</xliff:g>“"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d rásum bætt við</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Engum rásum bætt við"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Stillir"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Foreldraeftirlit"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Kveikt"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Slökkt"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Önnur lönd"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Engin"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ekkert"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Óflokkað"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Útiloka þætti án flokkunar"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ekkert"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Miklar takmarkanir"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Miðlungs takmarkanir"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Sláðu inn PIN-númerið til að horfa á þessa rás"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Sláðu inn PIN-númerið til að horfa á þennan þátt"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Þessi þáttur er flokkaður sem <xliff:g id="RATING">%1$s</xliff:g>. Sláðu inn PIN-númerið til að horfa á þáttinn"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Þessi þáttur er óflokkaður. Sláðu inn PIN-númerið til að horfa á þáttinn"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Sláðu inn PIN-númerið"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Til að stilla foreldraeftirlit skaltu búa til PIN-númer"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Sláðu inn nýtt PIN-númer"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Rangt PIN-númer. Reyndu aftur."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Reyndu aftur; PIN-númerin stemma ekki"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Sláðu inn póstnúmerið þitt."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Forritið Beinar útsendingar notar póstnúmerið þitt til að veita þér nákvæma sjónvarpsdagskrá."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Sláðu inn póstnúmerið þitt"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Ógilt póstnúmer"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Stillingar"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Sérsníða rásalista"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Veldu rásir fyrir dagskrárvísinn þinn"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Inntak rása"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nýjar rásir í boði"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Foreldraeftirlit"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Tímabreyting"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Taktu upp á meðan þú horfir svo þú getir gert hlé eða spólað til baka á útsendingu í beinni.\nViðvörun: Þetta getur dregið úr líftíma innbyggðrar geymslu vegna mikillar notkunar."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Leyfi opins kóða"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Leyfi opins kóða"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Senda ábendingu"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Útgáfa"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Til að horfa á þessa rás skaltu ýta til hægri og slá inn PIN-númerið þitt"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Til að horfa á þennan þátt skaltu ýta til hægri og slá inn PIN-númerið þitt"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Þessi þáttur er óflokkaður.\nTil að horfa á þennan þátt skaltu ýta til hægri og slá inn PIN-númerið"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Þessi þáttur er flokkaður sem <xliff:g id="RATING">%1$s</xliff:g>.\nTil að horfa á þáttinn skaltu ýta til hægri og slá inn PIN-númerið þitt."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Til að horfa á þessa rás skaltu nota sjálfgefna forritið fyrir sjónvarp í beinni útsendingu."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Til að horfa á þennan þátt skaltu nota sjálfgefna forritið fyrir sjónvarp í beinni útsendingu."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Þessi þáttur er óflokkaður.\nTil að horfa á þennan þátt skaltu nota sjálfgefna forritið fyrir sjónvarp í beinni útsendingu."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Þessi þáttur er flokkaður sem <xliff:g id="RATING">%1$s</xliff:g>.\nTil að horfa á þennan þátt skaltu nota sjálfgefna forritið fyrir sjónvarp í beinni útsendingu."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Þátturinn er læstur"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Þessi þáttur er óflokkaður"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Þessi dagskrárliður er flokkaður sem <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Aðeins hljóð"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Lítill sendistyrkur"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Ýttu á VELJA"</b>" til að fá aðgang að sjónvarpsvalmyndinni."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Ekkert sjónvarpsinntak fannst"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Sjónvarpsinntak finnst ekki"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Ekki er stuðningur við innfellda mynd"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Ekkert inntak er fyrir hendi til að nota í innfelldri mynd"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Gerð móttakara passar ekki. Ræstu forritið Rásir í beinni til að fá sjónvarpsinntak með móttakaragerð."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Stilling mistókst"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Ekkert forrit fannst sem getur framkvæmt þessa aðgerð."</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d upptaka á áætlun</item>
       <item quantity="other">%1$d upptökur á áætlun</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Hætta við upptöku"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Stöðva upptöku"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Horfa"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Spila frá upphafi"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Halda spilun áfram"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Þegar taka á upp of marga þætti á sama tíma eru aðeins þættir sem eru í forgangi teknir upp."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Vista"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Stakar upptökur hafa forgang"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Hætta við"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Hætta við"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Gleyma"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stöðva"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Skoða upptökuáætlun"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Bara þennan þátt"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Taka þetta upp í staðinn"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Hætta við þessa upptöku"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Horfa núna"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Eyða upptökum…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Hægt að taka upp"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Upptaka sett á áætlun"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Skarast á við aðra upptöku"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Upptaka í gangi"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Upptaka mistókst"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Les dagskrár til að búa til upptökuáætlanir"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Les dagskrár"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Skoðar þætti"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Skoða nýlegar upptökur"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Upptöku á <xliff:g id="PROGRAMNAME">%1$s</xliff:g> er ekki lokið."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Upptöku á <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> og <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> er ekki lokið."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Upptöku á <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> og <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> er ekki lokið."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Skortur á geymslurými kom í veg fyrir að upptöku á <xliff:g id="PROGRAMNAME">%1$s</xliff:g> væri lokið."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Skortur á geymslurými kom í veg fyrir að upptöku á <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> og <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> væri lokið."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Skortur á geymslurými kom í veg fyrir að upptöku á <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> og <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> væri lokið."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR þarf meira geymslupláss"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Þú getur tekið upp þætti með stafræna upptökubúnaðinum (DVR). Hins vegar er ekki nóg geymslupláss til staðar á tækinu þínu sem stendur til að DVR virki. Tengdu utanáliggjandi disk við tækið sem er <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB eða stærri og fylgdu skrefunum til að setja það upp sem geymslupláss tækisins."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Þú getur tekið upp þætti með stafræna upptökubúnaðinum (DVR). Hins vegar er ekki nóg geymslupláss til staðar á tækinu þínu sem stendur til að DVR virki. Tengdu utanáliggjandi disk við tækið sem er <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB eða stærri og fylgdu skrefunum til að setja það upp sem geymslupláss tækisins."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Of lítið geymslurými"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Þátturinn verður ekki tekinn upp þar sem of lítið geymslurými er til staðar. Prófaðu að eyða einhverjum af þeim upptökum sem eru þegar til staðar."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Geymslu vantar"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Hluta af geymslurýminu sem stafræni upptökubúnaðurinn notar vantar. Tengdu utanáliggjandi drif sem þú notaðir áður til að gera stafræna upptökubúnaðinn virkan á ný. Einnig geturðu valið að gleyma geymslunni ef hún er ekki lengur tiltæk."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Viltu gleyma geymslunni?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Allt efni sem þú hefur tekið upp og allar dagskrár glatast."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Stöðva upptöku?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Upptökur á efni verða vistaðar."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Upptöku á <xliff:g id="PROGRAMNAME">%1$s</xliff:g> verður hætt þar sem það skarast á við þennan þátt. Upptekið efni verður vistað."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Upptaka á áætlun en skarast við aðra"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Upptaka er hafin en hún skarast við aðra"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> verður tekið upp."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Sami þáttur er þegar á upptökuáætlun kl. <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Þegar tekið upp"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Þessi þáttur hefur þegar verið tekinn upp. Hann er tiltækur í DVR-safninu."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Upptaka þáttaseríu sett á áætlun"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> upptaka var sett á áætlun fyrir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> upptökur voru settar á áætlun fyrir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> upptökur voru settar á áætlun fyrir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> verður ekki tekið upp því að það skarast á við annað.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> upptökur voru settar á áætlun fyrir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> verður ekki tekið upp því að það skarast á við annað.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> upptaka var sett á áætlun fyrir <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> þættir úr þessari þáttaröð og í öðrum þáttaröðum verða ekki teknir upp því það skarast á við annað.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> upptökur voru settar á áætlun fyrir <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> þættir úr þessari þáttaröð og í öðrum þáttaröðum verða ekki teknir upp því það skarast á við annað.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> upptaka var sett á áætlun fyrir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Einn þáttur í annarri þáttaröð verður ekki tekinn upp því að hann skarast á við annað.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> upptökur voru settar á áætlun fyrir <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Einn þáttur í annarri þáttaröð verður ekki tekinn upp því að hann skarast á við annað.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> upptaka var sett á áætlun fyrir <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> þættir úr annarri þáttaröð verða ekki teknir upp því þeir skarast á við annað.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> upptökur voru settar á áætlun fyrir <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> þættir úr annarri þáttaröð verða ekki teknir upp því þeir skarast á við annað.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Upptekinn þáttur fannst ekki."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Tengdar upptökur"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Engin þáttalýsing)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d upptaka</item>
       <item quantity="other">%1$d upptökur</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Hætta upptöku á þáttaröð?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Upptökur af þáttum verða áfram tiltækar í DVR-safninu."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stöðva"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Ekki er verið að sýna þætti að svo stöddu."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Engir þættir eru tiltækir.\nÞeir verða teknir upp þegar þeir eru tiltækir."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d mínúta)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> í dag"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> á morgun"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Einkunn"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Upptökur af þáttum"</string>
 </resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index da0b48a..3f00e56 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Controlli riproduzione"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Canali recenti"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Canali"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opzioni TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opzioni PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Controlli di riproduzione non disponibili per questo canale"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Riproduci o metti in pausa"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avanza velocemente"</string>
@@ -35,39 +34,21 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Sottotitoli"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Visualizzazione"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Attiva"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Non attiva"</string>
-    <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
+    <string name="options_item_multi_audio" msgid="5118851311937896923">"Audio multilingua"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Trova altri canali"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Impostazioni"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Fonte"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Scambia"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Attiva"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Non attiva"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Suono"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principale"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Finestra PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"In basso a des."</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"In alto a des."</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"In alto a sin."</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"In basso a sin."</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Affiancata"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Dimensioni"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Grande"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Piccola"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Origine ingresso"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenna/cavo)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Nessuna informazione sul programma"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Nessuna informazione"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Canale bloccato"</string>
-    <string name="default_language" msgid="4122326459624337928">"Lingua sconosciuta"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Lingua sconosciuta"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Sottotitoli in %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Sottotitoli"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Off"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personalizza"</string>
-    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Imposta pref. di sistema per sottotitoli"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Imposta preferenze di sistema per i sottotitoli"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Visualizzazione"</string>
-    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Multi-audio"</string>
+    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Audio multilingua"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"mono"</string>
     <string name="multi_audio_channel_stereo" msgid="3758995659214256587">"stereo"</string>
     <string name="multi_audio_channel_surround_6" msgid="6066304966228963942">"Surround 5.1"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"Bassa definizione"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Raggruppa per"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Questo programma è bloccato"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Questo programma non è classificato"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Questo programma è classificato come <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"L\'ingresso non supporta la ricerca automatica"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Impossibile avviare la ricerca automatica per \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d canale aggiunto</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Nessun canale aggiunto"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sintonizzatore"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Controllo genitori"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Attivo"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Non attivo"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Altri Paesi"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Nessuno"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Nessuna"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Senza classificazione"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blocca i non classificati"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Nessuna"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Limitazioni alte"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Limitazioni medie"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Inserisci il codice PIN per guardare questo canale"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Inserisci il codice PIN per guardare questo programma"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"La valutazione di questo programma è <xliff:g id="RATING">%1$s</xliff:g>. Inserisci il tuo PIN per guardare il programma"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Questo programma non è classificato. Per guardarlo, inserisci il codice PIN."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Inserisci il codice PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Per impostare il filtro famiglia, crea un codice PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Inserisci il nuovo PIN"</string>
@@ -137,22 +121,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Il PIN è errato. Riprova."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Riprova, il PIN non corrisponde"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Inserisci il codice postale."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"L\'app Dirette TV userà il codice postale per fornire una guida ai programmi completa per i canali TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Inserisci il codice postale"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Codice postale non valido"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Impostazioni"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalizza canali"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Scegli canali per guida ai programmi"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Fonti canali"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nuovi canali disponibili"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Controllo genitori"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Registra i programmi in diretta mentre li guardi per poterli mettere in pausa o mandarli indietro.\nAvviso: l\'uso intensivo della memoria interna potrebbe ridurne la durata."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licenze open source"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licenze open source"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Invia feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versione"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Per guardare questo canale, premi il pulsante destro e inserisci il PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Per guardare questo programma, premi il pulsante destro e inserisci il PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Questo programma non è classificato.\nPer guardarlo, premi il pulsante destro e inserisci il codice PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Questo programma è classificato come <xliff:g id="RATING">%1$s</xliff:g>.\nPer guardarlo, premi il tasto destro e inserisci il PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Per guardare questo canale, utilizza l\'app predefinita per la trasmissione di contenuti TV in tempo reale."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Per guardare questo programma utilizza l\'app predefinita per la trasmissione di contenuti TV in tempo reale."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Questo programma non è classificato.\nPer guardarlo, utilizza l\'app predefinita per la trasmissione di contenuti TV in tempo reale."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"La valutazione di questo programma è <xliff:g id="RATING">%1$s</xliff:g>.\nPer guardare questo programma utilizza l\'app predefinita per la trasmissione di contenuti TV in tempo reale."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Il programma è bloccato"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Questo programma non è classificato"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Questo programma è classificato come <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Solo audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Segnale debole"</string>
@@ -170,7 +163,7 @@
       <item quantity="one">%1$d canale</item>
     </plurals>
     <string name="setup_input_no_channels" msgid="1669327912393163331">"Nessun canale disponibile"</string>
-    <string name="setup_input_new" msgid="3337725672277046798">"Elementi nuovi"</string>
+    <string name="setup_input_new" msgid="3337725672277046798">"Nuovo"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Non configurato"</string>
     <string name="setup_store_action_title" msgid="4083402039720973414">"Trova altre fonti"</string>
     <string name="setup_store_action_description" msgid="6820482635042445297">"Trova app che offrono dirette TV"</string>
@@ -183,17 +176,15 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Premi SELEZIONA"</b>" per accedere al menu della TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nessun ingresso TV trovato"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Impossibile trovare l\'ingresso TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Funzione PIP non supportata"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Nessun ingresso disponibile per visualizzazione PIP"</string>
-    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tipo di sintonizzatore non adatto. Avvia l\'app Live TV per l\'ingresso TV di tipo sintonizzatore."</string>
+    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tipo di sintonizzatore non adatto. Avvia l\'app Dirette TV per l\'ingresso TV di tipo sintonizzatore."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Sintonizzazione non riuscita"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Nessuna app trovata per gestire questa azione."</string>
     <string name="msg_all_channels_hidden" msgid="777397634062471936">"Tutti i canali di origine sono nascosti.\nSeleziona almeno un canale da guardare."</string>
     <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"Il video è improvvisamente non disponibile"</string>
     <string name="msg_back_key_guide" msgid="7404682718828721924">"Il tasto INDIETRO è per il dispositivo connesso. Per uscire premi il pulsante HOME."</string>
-    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Live TV richiede l\'autorizzazione per leggere gli elenchi TV."</string>
+    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Dirette TV richiede l\'autorizzazione per leggere gli elenchi TV."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Configura le tue fonti"</string>
-    <string name="setup_sources_description" msgid="5695518946225445202">"L\'app Dirette TV combina i canali TV tradizionali ai canali in streaming forniti dalle app. \n\nInnanzitutto, configura le fonti di canali già installate. In alternativa, cerca altre app di dirette TV sul Google Play Store."</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"L\'app Dirette TV combina i canali TV tradizionali con i canali in streaming forniti dalle app. \n\nInnanzitutto, configura le fonti di canali già installate. In alternativa, cerca altre app di dirette TV sul Google Play Store."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Registrazioni e programmazioni"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minuti"</string>
     <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 minuti"</string>
@@ -228,6 +219,8 @@
       <item quantity="other">%1$d registrazioni programmate</item>
       <item quantity="one">%1$d registrazione programmata</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Annulla registrazione"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Interrompi registrazione"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Guarda"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Riproduci dall\'inizio"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Riprendi riproduz."</string>
@@ -260,9 +253,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Quando ci sono troppi programmi da registrare nello stesso momento, vengono registrati solo quelli con le priorità maggiori."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Salva"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Le registrazioni uniche hanno la massima priorità"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Annulla"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Annulla"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Elimina"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Interrompi"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Pianificazione registrazione"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Solo questo programma"</string>
@@ -272,25 +262,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Registra questo"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Annulla la registrazione"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Guarda adesso"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Elimina registrazioni…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Registrabile"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Registrazione programmata"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Conflitto di registrazione"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Registrazione in corso"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Registrazione non riuscita"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Lettura dei programmi per la creazione delle pianificazioni di registrazione"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Lettura dei programmi…"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Lettura dei programmi…"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Visualizza registrazioni recenti"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"La registrazione di <xliff:g id="PROGRAMNAME">%1$s</xliff:g> è incompleta."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Le registrazioni di <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> e <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> sono incomplete."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Le registrazioni di <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> e <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> sono incomplete."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"La registrazione di <xliff:g id="PROGRAMNAME">%1$s</xliff:g> non è stata completata poiché lo spazio di archiviazione non era sufficiente."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Le registrazioni di <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> e <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> non sono state completate poiché lo spazio di archiviazione non era sufficiente."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Le registrazioni di <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> e <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> non sono state completate poiché lo spazio di archiviazione non era sufficiente."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Il dispositivo DVR ha bisogno di più spazio di archiviazione"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Potrai registrare programmi con un dispositivo DVR. Tuttavia, al momento lo spazio di archiviazione non è sufficiente per consentire il funzionamento del DVR. Collega un\'unità esterna di almeno <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB e segui la procedura per formattarla come memoria dispositivo."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Potrai registrare programmi con un dispositivo DVR. Tuttavia, al momento lo spazio di archiviazione non è sufficiente per consentire il funzionamento del DVR. Collega un\'unità esterna di almeno <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB e segui la procedura per formattarla come memoria dispositivo."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Spazio di archiviazione insufficiente"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Il programma non sarà registrato perché lo spazio di archiviazione non è sufficiente. Prova a eliminare alcune registrazioni esistenti."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Memoria mancante"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Manca parte della memoria utilizzata dal DVR. Collega l\'unità esterna utilizzata prima di riattivare il DVR. In alternativa, puoi scegliere di eliminare la memoria se non è più disponibile."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Eliminare la memoria?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Tutti i contenuti registrati e le pianificazioni andranno persi."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Interrompere la registrazione?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"I contenuti registrati verranno salvati."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"La registrazione di <xliff:g id="PROGRAMNAME">%1$s</xliff:g> verrà interrotta perché è in conflitto con questo programma. I contenuti registrati verranno salvati."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Registrazione programmata, ma ci sono conflitti"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"La registrazione è iniziata, ma ci sono conflitti"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Verrà registrato il programma <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -308,17 +301,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"È già stata programmata la registrazione dello stesso programma alle <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Già registrato"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Questo programma è già stato registrato. È disponibile nella raccolta DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Registrazione della serie programmata"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> registrazioni sono state pianificate per la serie <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> registrazione è stata pianificata per la serie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> registrazioni sono state pianificate per la serie <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> non saranno registrate a causa di conflitti.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> registrazione è stata pianificata per la serie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Non sarà registrata a causa di conflitti.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> registrazioni sono state pianificate per la serie <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> puntate di questa e altre serie non saranno registrate a causa di conflitti.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> registrazione è stata pianificata per la serie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> puntate di questa e altre serie non saranno registrate a causa di conflitti.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> registrazioni sono state pianificate per la serie <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Una puntata di un\'altra serie non sarà registrata a causa di conflitti.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> registrazione è stata pianificata per la serie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Una puntata di un\'altra serie non sarà registrata a causa di conflitti.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> registrazioni sono state pianificate per la serie <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> puntate di altre serie non saranno registrate a causa di conflitti.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> registrazione è stata pianificata per la serie <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> puntate di altre serie non saranno registrate a causa di conflitti.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Programma registrato non trovato."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Registrazioni correlate"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Nessuna descrizione programma)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d registrazioni</item>
       <item quantity="one">%1$d registrazione</item>
@@ -338,6 +343,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Interrompere la registrazione della serie?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Le puntate registrate resteranno disponibili nella raccolta DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Interrompi"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Nessuna puntata in onda al momento."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Non ci sono episodi a disposizione.\nVerranno registrati non appena saranno disponibili."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minuti)</item>
@@ -349,4 +355,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> di oggi"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> di domani"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Punteggio"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programmi registrati"</string>
 </resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 743b31f..6599d98 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"מונו"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"סטריאו"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"פקדי הפעלה"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"ערוצים אחרונים"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ערוצים"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"‏אפשרויות TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"‏אפשרויות PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"פקדי הפעלה אינם זמינים בשביל הערוץ הזה"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"הפעל או השהה"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"הרץ קדימה"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"כתוביות"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"מצב תצוגה"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"מופעל"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"כבוי"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"מולטי-אודיו"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"קבל ערוצים נוספים"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"הגדרות"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"מקור"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"החלף"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"מופעל"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"כבוי"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"צליל"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"ראשי"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"‏חלון PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"פריסה"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"שמאל למטה"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"שמאל למעלה"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ימין למעלה"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"ימין למטה"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"זה לצד זה"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"גודל"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"גדול"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"קטן"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"מקור קלט"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"טלוויזיה (אנטנה/כבלים)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"אין פרטי תכנית"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"אין מידע"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"ערוץ חסום"</string>
-    <string name="default_language" msgid="4122326459624337928">"שפה לא ידועה"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"שפה לא ידועה"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"‏כתוביות ב%1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"כתוביות"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"כבוי"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"התאם אישית את הפורמט"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"איכות רגילה"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"קבץ לפי"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"התכנית הזו חסומה"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"לתוכנית הזו אין סיווג תוכן"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"סיווג התכנית הזו הוא <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"הקלט אינו תומך בסריקה אוטומטית"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"לא ניתן להתחיל בסריקה אוטומטית עבור \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -94,7 +76,6 @@
       <item quantity="one">נוסף ערוץ אחד</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"לא נוספו ערוצים"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"טיונר"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"בקרות הוריות"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"מופעל"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"כבוי"</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"מדינות אחרות"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"ללא"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ללא"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"ללא סיווג תוכן"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"חסימת תוכניות ללא סיווג תוכן"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"ללא"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"הגבלות קפדניות"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"הגבלות בינוניות"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"הזן את קוד האימות שלך כדי לצפות בערוץ זה"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"הזן את קוד האימות שלך כדי לצפות בתכנית זו"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"‏סיווג התוכנית הזו הוא <xliff:g id="RATING">%1$s</xliff:g>. הזן את ה-PIN שלך כדי לצפות בתוכנית זו"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"‏לתוכנית הזו אין סיווג תוכן. עליך להזין את ה-PIN כדי לצפות בה"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"הזן את קוד האימות שלך"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"‏להגדרת בקרות הוריות, צור מספר PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"‏הזן את מספר ה-PIN החדש"</string>
@@ -139,22 +123,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"‏מספר ה-PIN היה שגוי. נסה שוב."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"נסה שוב, קוד האימות אינו תואם"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"הזן את המיקוד שלך"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"‏אפליקציית Live TV תשתמש במיקוד כדי לספק לך את לוח השידורים המלא של ערוצי הטלוויזיה."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"הזן את המיקוד שלך"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"מיקוד לא חוקי"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"הגדרות"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"התאם אישית רשימת ערוצים"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"בחר ערוצים ללוח השידורים שלך"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"מקורות של ערוצים"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"ערוצים חדשים זמינים"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"בקרת הורים"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"פקדי וידאו"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"אפשר להקליט את השידור בזמן הצפייה כדי להשהות תוכניות או להריץ אותן אחורה בזמן אמת.\nאזהרה: הפעלה של האפשרות הזו עלולה לקצר את חיי האחסון הפנימי עקב שימוש אינטנסיבי."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"רישיונות קוד פתוח"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"רישיונות קוד פתוח"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"שלח משוב"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"גרסה"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"‏כדי לצפות בערוץ הזה, לחץ על \'ימין\' והזן את מספר ה-PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"‏כדי לצפות בתכנית הזו, לחץ על \'ימין\' והזן את מספר ה-PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"‏לתוכנית הזו אין סיווג תוכן.\nכדי לצפות בה, יש ללחוץ על החץ ימינה ולהזין את ה-PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"‏סיווג התכנית הזו הוא <xliff:g id="RATING">%1$s</xliff:g>.\nכדי לצפות בתכנית, לחץ ימינה והזן את ה-PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"כדי לצפות בערוץ הזה, השתמש באפליקציית ברירת המחדל לטלוויזיה בשידור חי."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"כדי לצפות בתכנית זו, השתמש באפליקציית ברירת המחדל לטלוויזיה בשידור חי."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"לתוכנית הזו אין סיווג תוכן.\nכדי לצפות בה, יש להשתמש באפליקציית הטלוויזיה המוגדרת כברירת מחדל."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"סיווג התכנית הזו הוא <xliff:g id="RATING">%1$s</xliff:g>.\nכדי לצפות בתכנית זו, השתמש באפליקציית ברירת המחדל לטלוויזיה בשידור חי."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"התכנית חסומה"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"לתוכנית הזו אין סיווג תוכן"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"סיווג התכנית הזו הוא <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"אודיו בלבד"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"אות חלש"</string>
@@ -189,8 +182,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"לחץ על \'בחר\'"</b>" כדי לפתוח את תפריט הטלוויזיה."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"לא נמצא קלט טלוויזיה"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"לא ניתן למצוא את קלט הטלוויזיה"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"‏PIP אינו נתמך"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"‏אין קלט זמין הניתן להצגה באמצעות PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"סוג הטיונר אינו מתאים. הפעל את האפליקציה \'ערוצים בשידור חי\' בשביל טיונר מסוג קלט טלוויזיה."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"הכוונון נכשל"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"לא נמצאה אפליקציה שיכולה לטפל בפעולה הזו."</string>
@@ -244,6 +235,8 @@
       <item quantity="other">‏תוזמנו %1$d הקלטות</item>
       <item quantity="one">הקלטה אחת תוזמנה</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"בטל את ההקלטה"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"הפסק את ההקלטה"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"צפה"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"הפעל מההתחלה"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"המשך את ההפעלה"</string>
@@ -278,9 +271,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"כשיש יותר מדי תוכניות להקליט בו-זמנית, רק תוכניות בעלות עדיפות גבוהה יותר יוקלטו."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"שמור"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"הקלטות חד-פעמיות הן בעלות העדיפות הגבוהה ביותר"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"בטל"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"בטל"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"שכח"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"עצור"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"הצג לוח זמנים להקלטה"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"את התוכנית הזו בלבד"</string>
@@ -290,25 +280,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"הקלטת תוכנית זו במקום זאת"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ביטול הקלטה זאת"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"לצפייה עכשיו"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"מחיקת הקלטות…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"ניתנת להקלטה"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ההקלטה מתוזמנת"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"התנגשות בין הקלטות"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"מקליט"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ההקלטה נכשלה"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"קורא תוכניות כדי ליצור לוחות זמנים להקלטות"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"קורא תוכניות"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"קורא תוכניות"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"הצגת ההקלטות האחרונות"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"ההקלטה של <xliff:g id="PROGRAMNAME">%1$s</xliff:g> חלקית."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"ההקלטות של <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ו-<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> חלקיות."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"ההקלטות של <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ו-<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> חלקיות."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"ההקלטה של <xliff:g id="PROGRAMNAME">%1$s</xliff:g> לא הושלמה מפני ששטח האחסון אינו מספיק."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"ההקלטות של <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ו-<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> לא הושלמו מפני ששטח האחסון אינו מספיק."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"ההקלטות של <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ו-<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> לא הושלמו מפני ששטח האחסון אינו מספיק."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"‏DVR זקוק לשטח אחסון נוסף"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"‏תוכל להקליט תוכניות עם DVR. אולם, אין מספיק מקום אחסון במכשיר שלך כרגע כדי ש-DVR יעבוד. התחבר לכונן חיצוני בגודל GB<xliff:g id="STORAGE_SIZE">%1$s</xliff:g> או יותר, ובצע את השלבים לביצוע פורמט כאחסון מכשיר."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"‏תוכל להקליט תוכניות עם DVR. אולם, אין מספיק מקום אחסון במכשיר שלך כרגע כדי ש-DVR יעבוד. התחבר לכונן חיצוני בגודל GB<xliff:g id="STORAGE_SIZE">%1$d</xliff:g> או יותר, ובצע את השלבים לביצוע פורמט כאחסון מכשיר."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"אין מספיק שטח אחסון"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"התוכנית הזאת לא תוקלט מפני שאין מספיק שטח אחסון. נסה למחוק חלק מההקלטות הקיימות."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"אחסון חסר"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"‏חלק מהאחסון שנעשה בו שימוש ב-DVR חסר. חבר את הכונן החיצוני שבו השתמשת בעבר כדי להפעיל מחדש את ה-DVR. לחלופין, תוכל לבחור לשכוח את האחסון אם הוא אינו זמין עוד."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"לשכוח את האחסון?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"כל התוכן ולוחות הזמנים שתיעדת יאבדו."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"האם להפסיק את ההקלטה?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"התוכן המוקלט יישמר."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"ההקלטה של <xliff:g id="PROGRAMNAME">%1$s</xliff:g> תיפסק מפני שהיא מתנגשת עם התוכנית הזאת. התוכן שהוקלט יישמר."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ההקלטה מתוזמנת, אבל ישנן הקלטות מתנגשות."</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ההקלטה החלה, אבל ישנן הקלטות מתנגשות"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"התוכנית <xliff:g id="PROGRAMNAME">%1$s</xliff:g> תוקלט."</string>
@@ -328,17 +321,39 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"אותה תוכנית כבר תוזמנה להקלטה ב-<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"כבר הוקלט"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"‏תוכנית זו כבר הוקלטה. היא זמינה לצפייה בספריית ה-DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"הקלטת הסדרה תוזמנה"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="many"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">הקלטה <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> תוזמנה לסדרה <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> הקלטות מתוכן לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="many"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> הקלטות מתוכן לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> הקלטות מתוכן לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="one">הקלטה <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> תוזמנה לסדרה <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. היא לא תוקלט עקב התנגשויות.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> פרקים מסדרה זו וסדרה אחרת לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="many"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> פרקים מסדרה זו וסדרה אחרת לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> פרקים מסדרה זו וסדרה אחרת לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="one">הקלטה <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> תוזמנה לסדרה <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> פרקים מסדרה זו וסדרה אחרת לא יוקלטו עקב התנגשויות.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. פרק אחד מסדרה אחרת לא יוקלט עקב התנגשויות.</item>
+      <item quantity="many"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. פרק אחד מסדרה אחרת לא יוקלט עקב התנגשויות.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. פרק אחד מסדרה אחרת לא יוקלט עקב התנגשויות.</item>
+      <item quantity="one">הקלטה <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> תזומנה לסדרה <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. פרק אחד מסדרה אחרת לא יוקלט עקב התנגשויות.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> פרקים מסדרה אחרת לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="many"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> פרקים מסדרה אחרת לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> הקלטות תוזמנו לסדרה <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> פרקים מסדרה אחרת לא יוקלטו עקב התנגשויות.</item>
+      <item quantity="one">הקלטה <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> תוזמנה לסדרה <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> פרקים מסדרה אחרת לא יוקלטו עקב התנגשות.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"התוכנית המוקלטת לא נמצאה."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"הקלטות קשורות"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(אין תיאור לתוכנית)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="two">‏%1$d הקלטות</item>
       <item quantity="many">‏%1$d הקלטות</item>
@@ -362,6 +377,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"האם להפסיק את הקלטת הסדרה?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"‏פרקים מוקלטים יישארו זמינים בספריית DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"הפסק"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"אף פרק אינו משודר כעת."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"אין פרקים זמינים.\nהם יוקלטו כשיהיו זמינים."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="two">‏(%1$d דקות)</item>
@@ -375,4 +391,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> היום"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> מחר"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"ניקוד"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"תוכניות שהוקלטו"</string>
 </resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 9c526c2..47c2bf4 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"モノラル"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ステレオ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"再生操作"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"最近のチャンネル"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"チャンネル"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"テレビオプション"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIPオプション"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"このチャンネルでは再生操作を使用できません"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"再生または一時停止"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"早送り"</string>
@@ -30,38 +29,20 @@
     <string name="play_controls_description_skip_next" msgid="1603587562124694592">"次へ"</string>
     <string name="play_controls_description_skip_previous" msgid="3858447678278021381">"前へ"</string>
     <string name="channels_item_program_guide" msgid="2889807207930678418">"番組ガイド"</string>
-    <string name="channels_item_setup" msgid="6557412175737379022">"利用できる新しいチャンネル"</string>
+    <string name="channels_item_setup" msgid="6557412175737379022">"新しいチャンネル"</string>
     <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"<xliff:g id="APP_NAME">%1$s</xliff:g>を開く"</string>
     <string name="options_item_closed_caption" msgid="5945274655046367170">"字幕"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"表示モード"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"ON"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"OFF"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"マルチオーディオ"</string>
-    <string name="options_item_more_channels" msgid="971040969622943300">"その他のチャンネル"</string>
+    <string name="options_item_more_channels" msgid="971040969622943300">"他のチャンネル"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"設定"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"ソース"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"切り替え"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"ON"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"OFF"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"サウンド"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"メイン"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIPウィンドウ"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"レイアウト"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"右下"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"右上"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"左上"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"左下"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"横並び"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"サイズ"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"大"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"小"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"入力ソース"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"テレビ(アンテナ/ケーブル)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"プログラム情報がありません"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"情報はありません"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"ブロックされているチャンネル"</string>
-    <string name="default_language" msgid="4122326459624337928">"不明な言語"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"不明な言語"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"クローズド キャプション %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"字幕"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"OFF"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"書式設定のカスタマイズ"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"グループ化"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"このプログラムはブロックされています"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"この番組にはレーティングがありません"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"このプログラムのレーティングは<xliff:g id="RATING">%1$s</xliff:g>です"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"入力が自動スキャンをサポートしていません"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"「<xliff:g id="TV_INPUT">%s</xliff:g>」の自動スキャンを開始できません"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d 件のチャンネルが追加されました</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"追加されたチャンネルなし"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"チューナー"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"保護者による使用制限"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ON"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"OFF"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"その他の国"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"なし"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"なし"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"レーティングなし"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"レーティングなしの番組をブロック"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"なし"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"制限: 高"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"制限: 中"</string>
@@ -124,9 +107,10 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"PINを入力してこのチャンネルを視聴"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"PINを入力してこのプログラムを視聴"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"この番組は「<xliff:g id="RATING">%1$s</xliff:g>」レーティングです。この番組を視聴するには PIN を入力してください"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"この番組にはレーティングがありません。この番組を視聴するには PIN を入力してください"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PINの入力"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"保護者による使用制限を設定するには、暗証番号を作成してください"</string>
-    <string name="pin_enter_new_pin" msgid="1739471585849790384">"新しいPINを入力"</string>
+    <string name="pin_enter_new_pin" msgid="1739471585849790384">"新しい PIN を入力"</string>
     <string name="pin_enter_again" msgid="2618999754723090427">"PINの確認"</string>
     <string name="pin_enter_old_pin" msgid="4588282612931041919">"現在のPINの入力"</string>
     <plurals name="pin_enter_countdown" formatted="false" msgid="3415233538538544309">
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PINが正しくありません。もう一度お試しください。"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"もう一度お試しください。PINが一致しません。"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"郵便番号の入力"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"ライブ チャンネル アプリは、テレビ チャンネルの完全な番組ガイドを提供するために郵便番号を使用します。"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"郵便番号を入力してください"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"郵便番号が無効です"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"設定"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"チャンネル リストをカスタマイズ"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"番組ガイド用のチャンネルを選択します"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"チャンネル ソース"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"新しいチャンネルを利用できます"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"保護者による使用制限"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"タイムシフト"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"放送中の番組を視聴しながら録画する機能です。一時停止や巻き戻しができます。\n警告: 内部ストレージの負荷が増えるため、ストレージの寿命が短くなる恐れがあります。"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"オープンソース ライセンス"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"オープンソースライセンス"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"フィードバックを送信"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"バージョン"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"このチャンネルを視聴するには、右のボタンを押してPINを入力してください。"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"このプログラムを視聴するには、右のボタンを押してPINを入力してください。"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"この番組にはレーティングがありません。\nこの番組を視聴するには、右のボタンを押して PIN を入力してください"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"このプログラムのレーティングは<xliff:g id="RATING">%1$s</xliff:g>です。\nこのプログラムを視聴するには、右のボタンを押してPINを入力してください。"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"このチャンネルを視聴するには、デフォルトのライブテレビアプリを使用してください。"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"この番組を視聴するには、デフォルトのライブテレビアプリを使用してください。"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"この番組にはレーティングがありません。\nこの番組を視聴するには、デフォルトのライブテレビ アプリを使用してください。"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"この番組は「<xliff:g id="RATING">%1$s</xliff:g>」レーティングです。\nこの番組を視聴するには、デフォルトのライブテレビアプリを使用してください。"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"プログラムはブロックされています"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"この番組にはレーティングがありません"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"このプログラムのレーティングは<xliff:g id="RATING">%1$s</xliff:g>です"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"音声のみ"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"信号強度が弱くなっています"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"テレビのメニューにアクセスするには"<b>"[SELECT]を押してください"</b>"。"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"テレビ入力が見つかりませんでした"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"テレビ入力が見つかりません"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIPがサポートされていません"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIPで表示できる有効な入力はありません"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"無効なチューナータイプ。チューナー入力のライブチャンネルアプリを起動してください。"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"同調に失敗しました"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"この操作を行うアプリが見つかりませんでした。"</string>
@@ -193,10 +184,10 @@
     <string name="setup_sources_text" msgid="4988039637873759839">"ソースをセットアップ"</string>
     <string name="setup_sources_description" msgid="5695518946225445202">"ライブ チャンネルを利用すると、アプリで提供されるストリーミング チャンネルを従来のテレビのチャンネルと同様に視聴できます。\n\n使ってみるには、既にインストールされているチャンネル ソースをセットアップします。また、ライブ チャンネルを提供するアプリを Google Play ストアで探してさらに追加することもできます。"</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"録画予約"</string>
-    <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10分"</string>
-    <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30分"</string>
-    <string name="recording_start_dialog_1_hour_duration" msgid="7159533207022355641">"1時間"</string>
-    <string name="recording_start_dialog_3_hours_duration" msgid="295984419320006238">"3時間"</string>
+    <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 分"</string>
+    <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 分"</string>
+    <string name="recording_start_dialog_1_hour_duration" msgid="7159533207022355641">"1 時間"</string>
+    <string name="recording_start_dialog_3_hours_duration" msgid="295984419320006238">"3 時間"</string>
     <string name="dvr_main_recent" msgid="2553805424822806495">"最近"</string>
     <string name="dvr_main_scheduled" msgid="7837260963086408492">"予約済み"</string>
     <string name="dvr_main_series" msgid="8278256687595691676">"シリーズ"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d 件の録画予約</item>
       <item quantity="one">%1$d 件の録画予約</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"録画をキャンセル"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"録音を停止"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"再生"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"最初から再生"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"再生を再開"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"同時に多数の番組を録画する場合は、優先度の高い番組だけが録画されます。"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"保存"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"1 回のみの録画を最優先"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"キャンセル"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"キャンセル"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"削除"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"停止"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"録画予約を見る"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"この番組のみ"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"この番組を代わりに録画"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"この録画をキャンセル"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"今すぐ見る"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"録画の削除…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"録画できます"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"録画を予約しました"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"録画予約が重複しています"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"録画"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"録画に失敗しました"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"録画予約を作成する番組情報を読み取っています"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"番組情報を読み取っています"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"番組情報を読み取っています"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"最近の録画を表示"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"「<xliff:g id="PROGRAMNAME">%1$s</xliff:g>」の録画を完了できませんでした"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"「<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>」と「<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>」の録画を完了できませんでした"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"「<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>」、「<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>」、「<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>」の録画を完了できませんでした"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"ストレージの容量不足のため、「<xliff:g id="PROGRAMNAME">%1$s</xliff:g>」の録画を完了できませんでした。"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"ストレージの容量不足のため、「<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>」と「<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>」の録画を完了できませんでした。"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"ストレージの容量不足のため、「<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>」、「<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>」、「<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>」の録画を完了できませんでした。"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR のストレージ不足"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR を使用して番組を録画することはできますが、お使いの端末のストレージが十分ではないため、現在 DVR を使用できません。<xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB 以上の外部ストレージを接続し、手順に沿って端末のストレージと同じようにフォーマットしてください。"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR を使用して番組を録画することはできますが、お使いの端末のストレージが十分ではないため、現在 DVR を使用できません。<xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB 以上の外部ストレージを接続し、手順に沿って端末のストレージと同じようにフォーマットしてください。"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"空き容量の不足"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"空き容量が不足しているため、この番組は録画されません。録画済みの番組をいくつか削除してみてください。"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"ストレージにアクセスできません"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR で使用しているストレージの一部にアクセスできません。DVR を再度有効にする前に、使用している外部ドライブを接続してください。アクセスできないストレージは削除することもできます。"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"ストレージの削除"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"録画したコンテンツと録画予約がすべて失われます。"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"録音の停止"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"録画したコンテンツは保存されます。"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"「<xliff:g id="PROGRAMNAME">%1$s</xliff:g>」の録画は、この番組と重なっているため停止されます。録画したコンテンツは保存されます。"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"録画を予約しましたが、他の予約と重なっています"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"録画を開始しましたが、他の予約と重なっています"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"「<xliff:g id="PROGRAMNAME">%1$s</xliff:g>」が録画されます。"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"同じ番組が既に録画予約されています(<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>)。"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"録画済み"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"この番組は既に録画され、DVR ライブラリから利用できます。"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"シリーズの録画を予約しました"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">「<xliff:g id="SERIESNAME_3">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 件予約されています。</item>
+      <item quantity="one">「<xliff:g id="SERIESNAME_1">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 件予約されています。</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">「<xliff:g id="SERIESNAME_3">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 件予約されていますが、予約が競合するため <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> 件は録画されません。</item>
+      <item quantity="one">「<xliff:g id="SERIESNAME_1">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 件予約されていますが、予約が競合するため録画されません。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">「<xliff:g id="SERIESNAME_4">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> 件予約されています。予約が競合するため、このシリーズと他のシリーズのエピソード(<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> 件)は録画されません。</item>
+      <item quantity="one">「<xliff:g id="SERIESNAME_1">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 件予約されています。予約が競合するため、このシリーズと他のシリーズのエピソード(<xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> 件)は録画されません。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">「<xliff:g id="SERIESNAME_3">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 件予約されています。予約が競合するため、他のシリーズのエピソード(1 件)は録画されません。</item>
+      <item quantity="one">「<xliff:g id="SERIESNAME_1">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 件予約されています。予約が競合するため、他のシリーズのエピソード(1 件)は録画されません。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">「<xliff:g id="SERIESNAME_4">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> 件予約されています。予約が競合するため、他のシリーズのエピソード(<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> 件)は録画されません。</item>
+      <item quantity="one">「<xliff:g id="SERIESNAME_1">%2$s</xliff:g>」の録画は <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 件予約されています。予約が競合するため、他のシリーズのエピソード(<xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> 件)は録画されません。</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"録画された番組は見つかりませんでした。"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"関連の録画"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(番組の説明はありません)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d 件の録画</item>
       <item quantity="one">%1$d 件の録画</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"シリーズの録画を中止しますか?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"録画したエピソードは DVR ライブラリから利用できます。"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"停止"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"現在、放送中の番組はありません。"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"利用可能なエピソードはありません。\n利用可能になると録画されます。"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d分)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"今日(<xliff:g id="TIME_RANGE">%1$s</xliff:g>)"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"明日(<xliff:g id="TIME_RANGE">%1$s</xliff:g>)"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"スコア"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"録画した番組"</string>
 </resources>
diff --git a/res/values-ka-v23/strings.xml b/res/values-ka-rGE-v23/strings.xml
similarity index 100%
rename from res/values-ka-v23/strings.xml
rename to res/values-ka-rGE-v23/strings.xml
diff --git a/res/values-ka/arrays.xml b/res/values-ka-rGE/arrays.xml
similarity index 100%
rename from res/values-ka/arrays.xml
rename to res/values-ka-rGE/arrays.xml
diff --git a/res/values-ka/rating_system_strings.xml b/res/values-ka-rGE/rating_system_strings.xml
similarity index 100%
rename from res/values-ka/rating_system_strings.xml
rename to res/values-ka-rGE/rating_system_strings.xml
diff --git a/res/values-ka/strings.xml b/res/values-ka-rGE/strings.xml
similarity index 78%
rename from res/values-ka/strings.xml
rename to res/values-ka-rGE/strings.xml
index 72608bd..28c8ce3 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"მონო"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"სტერეო"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"ჩართვის კონტროლი"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"უახლესი არხები"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"არხები"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV პარამეტრები"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP პარამეტრები"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ამ არხისთვის არ არის ხელმისაწვდომი ჩართვის კონტროლი"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"დაკვრა ან პაუზა"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"წინ გადახვევა"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"დახურ.წარწერები"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"ჩვენების რეჟიმი"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"ჩართული"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"გამორთული"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"მულტი-აუდიო"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"მეტი არხის მიღება"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"პარამეტრები"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"წყარო"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"შენაცვლება"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"ჩართული"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"გამორთული"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ხმა"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"მთავარი"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP ფანჯარა"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"განლაგება"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"ქვედა მარჯვენა"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ზედა მარჯვენა"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ზედა მარცხენა"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"ქვედა მარცხენა"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"გვერდი-გვერდ"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"ზომა"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"დიდი"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"პატარა"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"შემავალი წყარო"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ტელევიზია (ანტენა/კაბელი)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"პროგრამის ინფორმაცია არ არის"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"ინფორმაცია არ არის ხელმისაწვდომი"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"დაბლოკილი არხი"</string>
-    <string name="default_language" msgid="4122326459624337928">"უცნობი ენა"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"უცნობი ენა"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"დახურული სუბტიტრები %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"დახურული სუბტიტრები"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"გამორთულია"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ფორმატირების მორგება"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"დაჯგუფება:"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"ეს პროგრამა დაბლოკილია"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"ეს პროგრამა შეუფასებელია"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"ამ პროგრამის რეიტინგია <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ავტო-სკანირება არ არის მხარდაჭერილი შეყვანით."</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"ვერ ხერხდება ავტო-სკანირება „<xliff:g id="TV_INPUT">%s</xliff:g>“-ისთვის"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">დაემატა %1$d არხი</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"არხები არ დამატებულა"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ტუნერი"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"მშობელთა კონტროლი"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ჩართულია"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"გამორთულია"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"სხვა ქვეყნები"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"არცერთი"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"არცერთი"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"შეუფასებელი"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"შეუფასებელ პროგრამათა დაბლოკვა"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"არცერთი"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"მაღალი შეზღუდვები"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"საშუალო შეზღუდვები"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"შეიყვანეთ თქვენი PIN ამ არხის საყურებლად"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"შეიყვანეთ თქვენი PIN ამ პროგრამის საყურებლად"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"ამ პროგრამის ასაკობრივი შეზღუდვაა: <xliff:g id="RATING">%1$s</xliff:g>. მის საყურებლად, შეიყვანეთ PIN-კოდი"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"ეს პროგრამა შეუფასებელია. ამ პროგრამის სანახავად, შეიყვანეთ თქვენი PIN-კოდი"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"შეიყვანეთ თქვენი PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"მშობელთა კონტროლის დასაყენებლად შექმენით PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"შეიყვანეთ ახალი PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"ეს PIN არასწორი იყო. ისევ სცადეთ."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"სცადეთ ისევ, PIN არ შეესაბამება"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"შეიყვანეთ თქვენი ZIP კოდი."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"სატელევიზიო არხების სრული პროგრამის სახელმძღვანელოს მისაწოდებლად, Live TV აპი ZIP კოდს გამოიყენებს."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"შეიყვანეთ თქვენი ZIP კოდი"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"არასწორი ZIP კოდი"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"პარამეტრები"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"არხების სიის მორგება"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"აირჩიეთ არხები პროგრამის სახელმძღვანელოსთვის"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"არხების წყაროები"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"ხელმისაწვდომია ახალი არხები"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"მშობელთა კონტროლი"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"დროის შეცვლა"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"ჩაიწერეთ ყურებისას, რათა შეძლოთ პირდაპირ ეთერში გაშვებული პროგრამების დაპაუზება და უკან გადახვევა.\nგაფრთხილება: ამ ქმედებამ შეიძლება შეამციროს შიდა მეხსიერების ფუნქციონირების პერიოდი, მისი ინტენსიური გამოყენების გამო."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"ღია კოდის ლიცენზიები"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"ღია კოდის ლიცენზიები"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"გამოხმაურება"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"ვერსია"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"ამ არხის საყურებლად დააჭირეთ „მარჯვენას“ და შეიყვანოთ თქვენი PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"ამ პროგრამის საყურებლად დააჭირეთ „მარჯვენას“ და შეიყვანოთ თქვენი PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"ეს პროგრამა შეუფასებელია.\nამ პროგრამის სანახავად, დააჭირეთ „მარჯვენას“ და შეიყვანეთ თქვენი PIN-კოდი."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"ამ პროგრამის რეიტინგია <xliff:g id="RATING">%1$s</xliff:g>.\nამ პროგრამის საყურებლად დააჭირეთ „მარჯვენას“ და შეიყვანოთ თქვენი PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ამ არხის საყურებლად, გამოიყენეთ პირდაპირი ტელევიზიის ნაგულისხმევი აპი."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"ამ პროგრამის საყურებლად, გამოიყენეთ პირდაპირი ტელევიზიის ნაგულისხმევი აპი."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"ეს პროგრამა შეუფასებელია.\nამ პროგრამის სანახავად, გამოიყენეთ პირდაპირი ტელევიზიის ნაგულისხმევი აპი."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"ამ პროგრამის რეიტინგია: <xliff:g id="RATING">%1$s</xliff:g>.\nამ პროგრამის საყურებლად, გამოიყენეთ პირდაპირი ტელევიზიის ნაგულისხმევი აპი."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"პროგრამა დაბლოკილია"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"ეს პროგრამა შეუფასებელია"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"ამ პროგრამის რეიტინგია <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"მხოლოდ აუდიო"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"სიგნალი სუსტია"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"დააჭირეთ არჩევას"</b>" სატელევიზიო მენიუზე წვდომისთვის."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"TV შეყვანა ვერ მოიძებნა."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV შეყვანა ვერ იძებნება."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"არ არის PIP-ის მხარდაჭერა."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP-ში გამოსაჩენი შემავალი სიგნალი მიუწვდომელია."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ტიუნერის ტიპი არ არის შესაფერისი; გთხოვთ გაუშვით პირდაპირი არხების აპი, სატელევიზიო შეტანის ტიუნერის ტიპისათვის."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"არხების დაჭერა ვერ მოხერხდა."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ამ მოქმედების შესასრულებლად აპი ვერ მოიძებნა."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d ჩანაწერი დაიგეგმა</item>
       <item quantity="one">%1$d ჩანაწერი დაიგეგმა</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"ჩაწერის გაუქმება"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"ჩაწერის შეწყვეტა"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ყურება"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"თავიდან დაკვრა"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"დაკვრის განახლება"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"თუ ჩასაწერად მეტისმეტად ბევრი პროგრამა დაიგეგმება, ჩაიწერება მხოლოდ მაღალი პრიორიტეტის მქონე პროგრამები."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"შენახვა"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ერთჯერად ჩანაწერებს მიენიჭოს მეტი პრიორიტეტი"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"გაუქმება"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"გაუქმება"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"დავიწყება"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"შეწყვეტა"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"ჩაწერის განრიგის ნახვა"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"მხოლოდ ეს პროგრამა"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"სანაცვლოდ, ჩაიწეროს ეს"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ამ ჩანაწერის გაუქმება"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"ახლავე ყურება"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ჩანაწერების წაშლა…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"შესაძლებელია ჩაწერა"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ჩაწერა დაგეგმილია"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ჩაწერის კონფლიქტი"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"მიმდინარეობს ჩაწერა"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ჩაწერა ვერ მოხერხდა"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"მიმდინარეობს პროგრამების წაკითხვა ჩაწერის განრიგების შესაქმნელად"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"მიმდინარეობს პროგრამების წაკითხვა"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"მიმდინარეობს პროგრამების წაკითხვა"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"ბოლო ჩანაწერების ნახვა"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> არასრულად ჩაიწერა."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> და <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> არასრულად ჩაიწერა."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> და <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> არასრულად ჩაიწერა."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"არასაკმარისი მეხსიერების გამო, <xliff:g id="PROGRAMNAME">%1$s</xliff:g> არასრულად ჩაიწერა."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"არასაკმარისი მეხსიერების გამო, <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> და <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> არასრულად ჩაიწერა."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"არასაკმარისი მეხსიერების გამო, <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> და <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> არასრულად ჩაიწერა."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR მეტ მეხსიერებას საჭიროებს"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR-ის მეშვეობით პროგრამების ჩაწერა შესაძლებელია, თუმცა თქვენს მოწყობილობაზე ამჟამად ხელმისაწვდომი მეხსიერება DVR-ის მუშაობისთვის არასაკმარისია. გთხოვთ, დააკავშიროთ <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> გბაიტი ან მეტი მოცულობის დისკწამყვანი და მიჰყვეთ ინსტრუქციას, რომელიც დაგეხმარებათ, დააფორმატოთ ის მოწყობილობის მეხსიერების სახით."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR-ის მეშვეობით პროგრამების ჩაწერა შესაძლებელია, თუმცა თქვენს მოწყობილობაზე ამჟამად ხელმისაწვდომი მეხსიერება DVR-ის მუშაობისთვის არასაკმარისია. გთხოვთ, დააკავშიროთ <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> გბაიტი ან მეტი მოცულობის დისკწამყვანი და მიჰყვეთ ინსტრუქციას, რომელიც დაგეხმარებათ, დააფორმატოთ ის მოწყობილობის მეხსიერების სახით."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"მეხსიერება არასაკმარისია"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"ეს პროგრამა ვერ ჩაიწერება არასაკმარისი მეხსიერების გამო. ცადეთ არსებული ჩანაწერების წაშლა."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"აკლია მეხსიერება"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR-ის მიერ გამოყენებული მეხსიერების ნაწილი ვერ მოიძებნა. DVR-ის ხელახლა ჩასართავად, გთხოვთ, დააკავშიროთ გარე დისკი, რომლითაც ადრე სარგებლობდით. თუ მეხსიერება ხელმისაწვდომი აღარ არის, შეგიძლიათ მეხსიერების დავიწყება აირჩიოთ."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"გსურთ მეხსიერების დავიწყება?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"მთელი თქვენი ჩაწერილი კონტენტი და ყველა განრიგი დაიკარგება."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"გსურთ ჩაწერის შეწყვეტა?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"ჩაწერილი კონტენტი შეინახება."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“-ის ჩაწერა შეწყდება ამ პროგრამასთან კონფლიქტის გამო. ჩაწერილი კონტენტი შეინახება."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ჩაწერა დაგეგმილია, თუმცა ის კონფლიქტშია"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ჩაწერა დაიწყო, თუმცა ის კონფლიქტშია"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ჩაიწერება."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"იგივე პროგრამა უკვე დაიგეგმა ჩასაწერად <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>-ზე."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"უკვე ჩაწერილია"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"ეს პროგრამა უკვე ჩაწერილია და DVR ბიბლიოთეკაშია ხელმისაწვდომი."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"სერიალის ჩაწერა დაგეგმილია"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">„<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ჩანაწერი.</item>
+      <item quantity="one">„<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ჩანაწერი.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">„<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ჩანაწერი. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> მათგანი ვერ ჩაიწერება კონფლიქტების გამო.</item>
+      <item quantity="one">„<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ჩანაწერი. ის ვერ ჩაიწერება კონფლიქტების გამო.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">„<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ჩანაწერი. ამ სერიალის <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ეპიზოდი და სხვა სერიალები ვერ ჩაიწერება კონფლიქტების გამო.</item>
+      <item quantity="one">„<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ჩანაწერი. ამ სერიალის <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ეპიზოდი და სხვა სერიალები ვერ ჩაიწერება კონფლიქტების გამო.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">„<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ჩანაწერი. სხვა სერიალის 1 ეპიზოდი ვერ ჩაიწერება კონფლიქტების გამო.</item>
+      <item quantity="one">„<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ჩანაწერი. სხვა სერიალის 1 ეპიზოდი ვერ ჩაიწერება კონფლიქტების გამო.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">„<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ჩანაწერი. სხვა სერიალების <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ეპიზოდი ვერ ჩაიწერება კონფლიქტების გამო.</item>
+      <item quantity="one">„<xliff:g id="SERIESNAME_1">%2$s</xliff:g>“-სთვის დაიგეგმა <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ჩანაწერი. სხვა სერიალების <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ეპიზოდი ვერ ჩაიწერება კონფლიქტების გამო.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"ჩაწერილი პროგრამა ვერ მოიძებნა."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"დაკავშირებული ჩანაწერები"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(პროგრამის აღწერა არ არის)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d ჩანაწერი</item>
       <item quantity="one">%1$d ჩანაწერი</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"გსურთ სერიალის ჩაწერის შეწყვეტა?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"ჩაწერილი ეპიზოდები DVR ბიბლიოთეკაში კვლავ იქნება ხელმისაწვდომი."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"შეწყვეტა"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ამჟამად ეთერში არცერთი ეპიზოდი არ გადის."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"ეპიზოდები მიუწვდომელია.\nმათი ჩაწერა მოხდება მაშინ, როცა ისინი ხელმისაწვდომი გახდება."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d წუთი)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"დღეს, <xliff:g id="TIME_RANGE">%1$s</xliff:g>-ზე"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"ხვალ, <xliff:g id="TIME_RANGE">%1$s</xliff:g>-ზე"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"შეფასება"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"ჩაწერილი პროგრამები"</string>
 </resources>
diff --git a/res/values-kk-v23/strings.xml b/res/values-kk-rKZ-v23/strings.xml
similarity index 100%
rename from res/values-kk-v23/strings.xml
rename to res/values-kk-rKZ-v23/strings.xml
diff --git a/res/values-kk/arrays.xml b/res/values-kk-rKZ/arrays.xml
similarity index 100%
rename from res/values-kk/arrays.xml
rename to res/values-kk-rKZ/arrays.xml
diff --git a/res/values-kk/rating_system_strings.xml b/res/values-kk-rKZ/rating_system_strings.xml
similarity index 100%
rename from res/values-kk/rating_system_strings.xml
rename to res/values-kk-rKZ/rating_system_strings.xml
diff --git a/res/values-kk/strings.xml b/res/values-kk-rKZ/strings.xml
similarity index 77%
rename from res/values-kk/strings.xml
rename to res/values-kk-rKZ/strings.xml
index 2a47972..4444119 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"моно"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"стерео"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Ойын тетіктері"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Жақ-ғы арналар"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Арналар"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"ТД опциялары"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP опциялары"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Бұл арна үшін ойнатуды басқару элементтерін қол жетімсіз"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Ойнату немесе кідірту"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Жылдам алға айналдыру"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Жасырын титрлер"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Дисплей режимі"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Қосулы"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Өшірулі"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Мультиаудио"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Басқа арналар"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Параметрлер"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Көз"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Алмастыру"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Қосулы"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Өшірулі"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Дыбыс"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Негізгі"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP терезесі"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Орналасу"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Төменгі оң жақ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Жоғарғы оң жақ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Жоғарғы сол жақ"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Төменгі сол жақ"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Қатар"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Өлшем"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Үлкен"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Кішкентай"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Енгізу көзі"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ТД (антенна/кабель)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Бағдарлама туралы ақпарат жоқ"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Ақпарат жоқ"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Бөгелген арна"</string>
-    <string name="default_language" msgid="4122326459624337928">"Белгісіз тіл"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Белгісіз тіл"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Субтитрлер: %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Жасырын титрлер"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Өшірулі"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Пішімдеуді теңшеу"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Топтау шарты"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Бұл бағдарламаға тыйым салынған"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Бұл бағдарламаның жас бойынша шектеуі белгіленбеген"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Бұл бағдарламаға <xliff:g id="RATING">%1$s</xliff:g> бағасы қойылған"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Кіріс автоматты түрде іздеуді қолдамайды"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"«<xliff:g id="TV_INPUT">%s</xliff:g>» үшін автоматты түрде іздеуді бастау мүмкін болмады"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d арна қосылды</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Арналар қосылмаған"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Тюнер"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Ата-аналық бақылау"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Қосулы"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Өшірулі"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Басқа елдер"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ешқандай"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ешқандай"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Жас бойынша шектеуі белгіленбеген"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Жас бойынша шектеуі белгіленбеген бағдарламаларды бөгеу"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ешқандай"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Жоғары шектеулер"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Орташа шектеулер"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Бұл арнаны көру үшін PIN кодын енгізіңіз"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Бұл бағдарламаны көру үшін PIN кодын енгізіңіз"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Бұл бағдарламаға <xliff:g id="RATING">%1$s</xliff:g> бағасы берілген. Оны көру үшін PIN кодын енгізіңіз"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Бұл бағдарламаның жас бойынша шектеуі белгіленбеген. Бұл бағдарламаны көру үшін PIN кодын енгізіңіз"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PIN кодын енгізіңіз"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Ата-аналық бақылауды орнату үшін PIN кодын жасаңыз"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Жаңа PIN кодын енгізіңіз"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Бұл PIN қате болды. Әрекетті қайталаңыз."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Әрекетті қайталаңыз, PIN кодтары сәйкес емес"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Пошта индексін енгізіңіз."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Тікелей арналар қолданбасы телеарналардың толық бағдарламалар нұсқаулығын ұсыну үшін пошта индексін пайдаланады."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Индексті енгізіңіз"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Индекс жарамсыз"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Параметрлер"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Арналар тізімін теңшеу"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Бағдарлама нұсқаулығына арналған арналарды таңдау"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Арна көздері"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Жаңа арналар қосылды"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Ата-аналық бақылау"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Уақытты жылжыту"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Тікелей эфирдегі бағдарламаларды көру кезінде тоқтатуға немесе артқа айналдыруға болатын жазу.\nЕскерту: бұл жадты қарқынды пайдалану арқылы ішкі жадтың қызмет көрсету мерзімін азайтуы мүмкін."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Ашық бастапқы код лицензиялары"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Ашық бастапқы код лицензиялары"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Пікір жіберу"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Нұсқа"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Бұл арнаны көру үшін оңға түймесін басып, PIN кодын енгізіңіз"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Бұл бағдарламаны көру үшін оңға түймесін басып, PIN кодын енгізіңіз"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Бұл бағдарламаның жас бойынша шектеуі белгіленбеген.\nБұл бағдарламаны көру үшін оң жаққа бағытталған көрсеткіні басып, PIN кодын енгізіңіз"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Бұл бағдарламаға <xliff:g id="RATING">%1$s</xliff:g> бағасы қойылған.\nБұл бағдарламаны көру үшін \"Оңға\" түймесін басып, PIN кодын енгізіңіз."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Бұл арнаны көру үшін әдепкі Live TV қолданбасын пайдаланыңыз."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Бұл бағдарламаны көру үшін әдепкі Live TV қолданбасын пайдаланыңыз."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Бұл бағдарламаның жас бойынша шектеуі белгіленбеген.\nБұл бағдарламаны көру үшін әдепкі Live TV қолданбасын пайдаланыңыз."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Бұл бағдарлама <xliff:g id="RATING">%1$s</xliff:g> болып бағаланды.\nБұл бағдарламаны көру үшін әдепкі Live TV қолданбасын пайдаланыңыз."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Бағдарлама бөгелген"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Бұл бағдарламаның жас бойынша шектеуі белгіленбеген"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Бұл бағдарламаға <xliff:g id="RATING">%1$s</xliff:g> бағасы қойылған"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Тек аудио"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Cигнал әлсіз"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Теледидар мәзіріне кіру үшін ТАҢДАУ"</b>" түймесін басыңыз."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"ТД кіріс сигналы табылмады"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"ТД кіріс сигналын табу мүмкін емес"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP мүмкіндігіне қолдау көрсетілмейді"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP мүмкіндігімен көрсетуге болатын кіріс сигналы жоқ"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Тюнер түрі жарамсыз. Тюнер түрінің ТД кіріс сигналы үшін Тікелей эфир арналары қолданбасын іске қосыңыз."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Арнаға реттелмеді"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Бұл әрекетті орындайтын қолданба табылмады."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d жазба жоспарланды</item>
       <item quantity="one">%1$d жазба жоспарланды</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Жазудан бас тарту"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Жазуды тоқтату"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Сағат"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Басынан бастап ойнату"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Ойнатуды жалғастыру"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Бір мезгілде тым көп бағдарламаны жазып алу қажет болса, тек маңыздылығы жоғарылары ғана жазылады."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Сақтау"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Бір жолғы жазбалар ең маңызды болып табылады"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Бас тарту"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Бас тарту"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Жою"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Тоқтату"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Жазу кестесін көру"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Тек осы бағдарлама"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Орнына мына бағдарламаны жазу"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Бұл жазып алу кестесінен бас тарту"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Қазір көру"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Жазбалар жойылуда…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Жазып алуға болады"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Жазып алынады"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Жазу кестесінде қайшылық бар"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Жазылуда"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Жазу сәтсіз аяқталды"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Жазу кестелерін жасауға арналған оқу бағдарламалары"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Бағдарлама ақпараты оқылуда"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Бағдарлама ақпараты оқылуда"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Соңғы жазбаларды көру"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> бағдарламасын жазу аяқталмады."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> және <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> бағдарламасын жазу аяқталмады."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> және <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> бағдарламасын жазу аяқталмады."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Жад жеткіліксіз болғандықтан, <xliff:g id="PROGRAMNAME">%1$s</xliff:g> бағдарламасын жазу аяқталмады."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Жад жеткіліксіз болғандықтан, <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> және <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> бағдарламасын жазу аяқталмады."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Жад жеткіліксіз болғандықтан, <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> және <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> бағдарламасын жазу аяқталмады."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR көбірек бос орынды қажет етеді"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Бағдарламаларды DVR арқылы жазып алуға болады. Алайда DVR жұмысы үшін құрылғыда бос орын жеткіліксіз. <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> ГБ не одан үлкен сыртқы дискіні жалғап, оны құрылғы жады ретінде форматтау қадамдарын орындаңыз."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Бағдарламаларды DVR арқылы жазып алуға болады. Алайда DVR жұмысы үшін құрылғыда бос орын жеткіліксіз. <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> ГБ не одан үлкен сыртқы дискіні жалғап, оны құрылғы жады ретінде форматтау қадамдарын орындаңыз."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Жадта орын жеткіліксіз"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Жадта орын жеткіліксіз болғандықтан, бұл бағдарлама жазылмайды. Кейбір бұрыннан бар жазбаларды жойыңыз."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Жад жоқ"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR пайдаланатын жадтың бір бөлігі жоқ. DVR құрылғысын қайта іске қосу үшін бұрын пайдаланған сыртқы дискіні жалғаңыз. Сондай-ақ егер жад бұдан әрі қолжетімді болмаса, оны жоюыңызға болады."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Жад жойылсын ба?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Барлық жазылған мазмұндар мен кестелер жойылады."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Жазу тоқтатылсын ба?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Жазылған мазмұн сақталады."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Осы бағдарламамен қайшылық тудырғандықтан, <xliff:g id="PROGRAMNAME">%1$s</xliff:g> жазу тоқтатылды. Жазып алынған мазмұн сақталады."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Жоспарланған, бірақ қайшылықтары бар"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Жазу басталды, бірақ қайшылықтары бар"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> жазылады."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Бұл бағдарламаны жазып алу басқа уақытқа (<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>) әлдеқашан жоспарланған."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Бұрын жазылған"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Бұл бағдарлама бұрын жазылған және DVR кітапханасында бар."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Серияларды жазып алу жоспарланды"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> жазба жоспарланды.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жазба жоспарланды.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> жазба жоспарланды. Олардың ішінде <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> серия қайшылықтарға байланысты жазылмайды.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жазба жоспарланды. Ол қайшылықтарға байланысты жазылмайды.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> жазба жоспарланды. Бұл сериалдың және басқа сериалдың <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> сериясы қайшылықтарға байланысты жазылмайды.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жазба жоспарланды. Бұл сериалдың және басқа сериалдың <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> сериясы қайшылықтарға байланысты жазылмайды.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> жазба жоспарланды. Басқа сериалдың 1 сериясы қайшылықтарға байланысты жазылмайды.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жазба жоспарланды. Басқа сериалдың 1 сериясы қайшылықтарға байланысты жазылмайды.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> жазба .жоспарланды. Басқа сериалдың <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> сериясы қайшылықтарға байланысты жазылмайды.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> үшін <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жазба .жоспарланды. Басқа сериалдың <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> сериясы қайшылықтарға байланысты жазылмайды.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Жазылған бағдарлама табылмады."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Қатысты жазбалар"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Бағдарлама сипаттамасы жоқ)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d жазба</item>
       <item quantity="one">%1$d жазба</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Серияларды жазу тоқтатылсын ба?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Жазылған серияларды DVR кітапханасынан алуға болады."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Тоқтату"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Ешқандай серия көрсетіліп жатқан жоқ."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Ешқандай серия қолжетімді емес.\nОларды қолжетімді болған кезде ғана жазып алуға болады."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d минут)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Бүгін <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Ертең <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Ұпай саны"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Жазылған бағдарламалар"</string>
 </resources>
diff --git a/res/values-km-v23/strings.xml b/res/values-km-rKH-v23/strings.xml
similarity index 100%
rename from res/values-km-v23/strings.xml
rename to res/values-km-rKH-v23/strings.xml
diff --git a/res/values-km/arrays.xml b/res/values-km-rKH/arrays.xml
similarity index 100%
rename from res/values-km/arrays.xml
rename to res/values-km-rKH/arrays.xml
diff --git a/res/values-km/rating_system_strings.xml b/res/values-km-rKH/rating_system_strings.xml
similarity index 100%
rename from res/values-km/rating_system_strings.xml
rename to res/values-km-rKH/rating_system_strings.xml
diff --git a/res/values-km/strings.xml b/res/values-km-rKH/strings.xml
similarity index 77%
rename from res/values-km/strings.xml
rename to res/values-km-rKH/strings.xml
index 98fa13f..ca2c337 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"ម៉ូណូ"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ស្តេរ៉េអូ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"បញ្ជាការចាក់"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"ឆានែល​ថ្មីៗ"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ឆានែល"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"ជម្រើសទូរទស្សន៍"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"ជម្រើស PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ការបញ្ជាលើការចាក់មិនអាចប្រើបានទេសម្រាប់ឆានែលនេះ។"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"ចាក់ ឬផ្អាក"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"ទៅមុខរហ័ស"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"ចំណងជើង​បិទ"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"របៀប​បង្ហាញ"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"បើក"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"បិទ"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"ពហុ​អូឌីយ៉ូ"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"ទទួលយកប៉ុស្តិ៍ជាច្រើនទៀត"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"ការកំណត់"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"ប្រភព"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"ប្ដូរ"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"បើក"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"បិទ"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"សំឡេង"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"ចម្បង"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"ផ្ទាំងវិនដូ PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"ប្លង់"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"បាតខាងស្តាំ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ចុងខាងស្តាំ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ចុងខាងឆ្វេង"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"បាតខាងឆ្វេង"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"នៅក្បែរគ្នា"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"ទំហំ"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"ធំ"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"តូច"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"ប្រភព​ចូល"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ទូរទស្សន៍ (អង់តែន/ខ្សែកាប)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"មិន​មាន​ព័ត៌មាន​កម្មវិធី"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"មិនមានព័ត៌មានទេ"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"បណ្តាញដែលបានរារាំង"</string>
-    <string name="default_language" msgid="4122326459624337928">"ភាសាមិនស្គាល់"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"ភាសាមិនស្គាល់"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"អក្សរ​រត់ %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"បានបិទចំណងជើង"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"បិទ"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ប្ដូររាងតាមត្រូវការ"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"ដាក់​ជា​ក្រុម​តាម"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"កម្មវិធីនេះត្រូវបានរារាំង"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"កម្មវិធីនេះមិនបានវាយតម្លៃទេ"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"កម្មវិធីនេះត្រូវបានវាយតម្លៃ <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ការ​បញ្ចូល​មិន​គាំទ្រ​ការ​វិភាគ​រក​ស្វ័យ​ប្រវត្តិ"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"មិន​អាច​ចាប់ផ្ដើម​ការ​វិភាគ​ស្វ័យប្រវត្តិ​សម្រាប់ \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">បានបន្ថែមប៉ុស្តិ៍ %1$d</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"គ្មាន​ឆា​នែ​ល​បាន​បន្ថែម"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"ការ​ត្រួតពិនិត្យមេ"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"បើក"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"បិទ"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"ប្រទេសផ្សេងទៀត"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"គ្មាន"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"គ្មាន"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"មិនបានវាយតម្លៃ"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"ទប់ស្កាត់កម្មវិធីដែលមិនបានវាយតម្លៃ"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"គ្មាន"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"ការ​ដាក់កម្រិត​ខ្ពស់"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"ការដាក់កម្រិតមធ្យម"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"បញ្ចូល​កូដ PIN របស់​អ្នក​ដើម្បី​មើល​​ឆានែល​នេះ"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"បញ្ចូល​កូដ PIN របស់​អ្នក​ដើម្បី​មើល​កម្មវិធី​នេះ"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"កម្មវិធីនេះត្រូវបានវាយតម្លៃ <xliff:g id="RATING">%1$s</xliff:g>។ បញ្ចូលកូដ PIN របស់អ្នកដើម្បីមើលកម្មវិធីនេះ"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"កម្មវិធីនេះមិនបានវាយតម្លៃទេ។ បញ្ចូលកូដ PIN របស់អ្នក ដើម្បីមើលកម្មវិធីនេះ"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"បញ្ចូល​កូដ PIN របស់​អ្នក"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"ដើម្បី​កំណត់​ការ​ពិនិត្យ​របស់​ឪពុកម្ដាយ អ្នក​ត្រូវ​បង្កើត​កូដ PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"បញ្ចូល​កូដ PIN ថ្មី"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"កូដ PIN មិន​ត្រឹមត្រូវ។ ព្យាយាម​ម្ដងទៀត។"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"ព្យាយាម​ម្ដង​ទៀត កូដ​ PIN មិន​ដូច​គ្នា"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"បញ្ចូល​លេខ​កូដ​តំបន់​របស់អ្នក។"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"កម្មវិធី​ប៉ុស្តិ៍​ផ្សាយ​ផ្ទាល់​នឹង​ប្រើ​លេខ​កូដ​តំបន់ ដើម្បី​ផ្តល់ជូន​នូវ​ការ​ណែនាំ​អំពីកម្មវិធី​ទាំងស្រុង​សម្រាប់​ប៉ុស្តិ៍​ទូរទស្សន៍។"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"បញ្ចូល​លេខកូដ​តំបន់​របស់​អ្នក"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"លេខកូដ​តំបន់​មិនត្រឹមត្រូវ​ទេ"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"ការកំណត់"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"ប្ដូរបញ្ជីប៉ុស្តិ៍តាមបំណង"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"ជ្រើសប៉ុស្តិ៍សម្រាប់ការណែនាំកម្មវិធីរបស់អ្នក"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"ប្រភពប៉ុស្តិ៍"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"មានប៉ុស្តិ៍ថ្មី"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"ការគ្រប់គ្រងដោយមាតាបិតា"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"ការថតទុកមើលពេលក្រោយ"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"ថតខណៈពេលកំពុងទស្សនា ដើម្បីឲ្យអ្នកអាចផ្អាក ឬខាកម្មវិធីផ្សាយ​​ផ្ទាល់ថយក្រោយបាន។\nព្រមាន៖ វាអាចកាត់បន្ថយអាយុកាលប្រើប្រាស់ទំហំផ្ទុកខាងក្នុង ដោយសារការប្រើប្រាស់ទំហំផ្ទុកយ៉ាងច្រើន។"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"អាជ្ញាប័ណ្ណប្រភពកូដបើកចំហ"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"អាជ្ញាប័ណ្ណប្រភពកូដចំហ"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ផ្ញើមតិស្ថាបនា"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"កំណែ"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"ដើម្បី​មើល​ឆានែល​នេះ អ្នក​ត្រូវ​ចុច​កណ្ដុរស្ដាំ រួច​បញ្ចូល​កូដ PIN របស់​អ្នក"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"ដើម្បី​មើល​កម្មវិធី​នេះ អ្នក​ត្រូវ​ចុច​កណ្ដុរស្ដាំ រួច​បញ្ចូល​កូដ PIN របស់​អ្នក"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"កម្មវិធីនេះមិនបានវាយតម្លៃទេ។\nដើម្បីមើលកម្មវិធីនេះ សូមចុច ស្ដាំ រួចបញ្ចូលកូដ PIN របស់អ្នក"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"កម្មវិធីនេះត្រូវបានវាយតម្លៃ <xliff:g id="RATING">%1$s</xliff:g>។\n ដើម្បីមើលកម្មវិធីនេះ សូមចុច ស្តាំ រួចបញ្ចូលកូដ PIN របស់អ្នក។"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ដើម្បីមើលប៉ុស្តិ៍នេះ សូមប្រើកម្មវិធីទូរទស្សន៍ផ្សាយផ្ទាល់លំនាំដើម"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"ដើម្បីមើលកម្មវិធីនេះ សូមប្រើកម្មវិធីទូរទស្សន៍ផ្សាយផ្ទាល់លំនាំដើម"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"កម្មវិធីនេះមិនបានវាយតម្លៃទេ។\nដើម្បីមើលកម្មវិធីនេះ សូមប្រើកម្មវិធីទូរទស្សន៍ផ្សាយផ្ទាល់លំនាំដើម។"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"កម្មវិធីនេះត្រូវបានវាយតម្លៃ <xliff:g id="RATING">%1$s</xliff:g>\nដើម្បីមើលកម្មវិធីនេះ សូមប្រើកម្មវិធីទូរទស្សន៍ផ្សាយផ្ទាល់លំនាំដើម"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"កម្មវិធី​នេះ​ត្រូវ​បាន​ទប់ស្កាត់"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"កម្មវិធីនេះមិនបានវាយតម្លៃទេ"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"កម្មវិធីនេះត្រូវបានវាយតម្លៃ <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"តែ​អូឌីយ៉ូ​ប៉ុណ្ណោះ"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"សញ្ញា​ខ្សោយ"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"ចុច ជ្រើសរើស"</b>" ដើម្បីចូលប្រើម៉ឺនុយទូរទស្សន៍។"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"រកមិនឃើញបញ្ចូលទូរទស្សន៍ទេ"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"រកមិនឃើញបញ្ចូលទូរទស្សន៍ទេ"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"មិនគាំទ្រ PIP ទេ។"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"មិនមានបញ្ចូលដែលអាចបង្ហាញជាមួយ PIP បានទេ។"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ប្រភេទឧបករណ៍ចាប់ប៉ុស្តិ៍មិនសមស្រប។ សូមចាប់ផ្តើមដំណើរការកម្មវិធី ប៉ុស្តិ៍ផ្សាយផ្ទាល់ សម្រាប់ធាតុបញ្ជូលទូរទស្សន៍ប្រភេទឧបករណ៍ចាប់ប៉ុស្តិ៍។"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"កាកែសម្រួលប៉ុស្តិ៍បានបរាជ័យ"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"រកមិនឃើញកម្មវិធីដើម្បីគ្រប់គ្រងសកម្មភាពនេះទេ។"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">ការថតដែលបានកំណត់ពេល %1$d</item>
       <item quantity="one">ការថតដែលបានកំណត់ពេល %1$d</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"បោះបង់ការថត"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"បញ្ឈប់ការថត"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ទស្សនា"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"ចាក់ពីដំបូង"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"ចាក់​បន្ត"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"នៅពេលដែលមានកម្មវិធីដែលត្រូវថតច្រើនពេកក្នុងពេលតែមួយ នោះមានតែកម្មវិធីដែលមានអាទិភាពខ្ពស់ជាងប៉ុណ្ណោះដែលនឹងត្រូវថត។"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"រក្សាទុក"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ការថតមួយដងមានអាទិភាពខ្ពស់បំផុត"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"បោះបង់"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"បោះបង់"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"បំភ្លេច"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"បញ្ឈប់"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"មើលកាលវិភាគថត"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"កម្មវិធីមួយនេះ"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"ថតកម្មវិធីនេះជំនួសវិញ"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"បោះបង់ការថតនេះ"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"មើលឥឡូវនេះ"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"លុបការថត…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"អាចថតបាន"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"បានកំណត់ពេលការថត"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ការថតជាន់ម៉ោងគ្នា"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"ការថត"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"បានបរាជ័យក្នុងការថត"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"កំពុងអានកម្មវិធីដើម្បីបង្កើតកាលវិភាគថត"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"កំពុងអានកម្មវិធី"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"កំពុងអានកម្មវិធី"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"មើលការថតថ្មីៗ"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"ការថត <xliff:g id="PROGRAMNAME">%1$s</xliff:g> មិនទាន់បញ្ចប់ទេ។"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"ការថត <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> និង <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> មិនទាន់បញ្ចប់ទេ។"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"ការថត <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> និង <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> មិនទាន់បញ្ចប់ទេ។"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"ការថត <xliff:g id="PROGRAMNAME">%1$s</xliff:g> មិនបានបញ្ចប់ទេ ដោយសារមិនមានទំហំផ្ទុកគ្រប់គ្រាន់។"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"ការថត <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> និង <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> មិនបានបញ្ចប់ទេ ដោយសារមិនមានទំហំផ្ទុកគ្រប់គ្រាន់។"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"ការថត <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> និង <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> មិនបានបញ្ចប់ទេ ដោយសារមិនមានទំហំផ្ទុកគ្រប់គ្រាន់។"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR ត្រូវការទំហំផ្ទុកបន្ថែមទៀត"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"អ្នកនឹងអាចថតកម្មវិធីដោយប្រើ DVR។ ទោះបីជាយ៉ាងណាក៏ដោយ ឥឡូវនេះមិនមានទំហំផ្ទុកគ្រប់គ្រាន់នៅលើឧបករណ៍របស់អ្នកដើម្បីអនុញ្ញាតឲ្យ DVR ដំណើរការនោះទេ។ សូមភ្ជាប់ទៅឧបករណ៍ផ្ទុកខាងក្រៅដែលមានទំហំផ្ទុក <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB ឬធំជាងនេះ បន្ទាប់មកអនុវត្តតាមជំហានទាំងនេះដើម្បីសម្អាតវាក្នុងនាមជាឧបករណ៍ផ្ទុក។"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"អ្នកនឹងអាចថតកម្មវិធីដោយប្រើ DVR។ ទោះបីជាយ៉ាងណាក៏ដោយ ឥឡូវនេះមិនមានទំហំផ្ទុកគ្រប់គ្រាន់នៅលើឧបករណ៍របស់អ្នកដើម្បីអនុញ្ញាតឲ្យ DVR ដំណើរការនោះទេ។ សូមភ្ជាប់ទៅឧបករណ៍ផ្ទុកខាងក្រៅដែលមានទំហំផ្ទុក <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB ឬធំជាងនេះ បន្ទាប់មកអនុវត្តតាមជំហានទាំងនេះដើម្បីសម្អាតវាក្នុងនាមជាឧបករណ៍ផ្ទុក។"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"មិនមានទំហំផ្ទុកគ្រប់គ្រាន់ទេ"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"មិនអាចថតកម្មវិធីនេះបានទេ ដោយសារតែមិនមានទំហំផ្ទុកគ្រប់គ្រាន់។ សូមសាកល្បងលុបការថតមួយចំនួនដែលមានស្រាប់។"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"ឧបករណ៍ផ្ទុកដែលបានបាត់"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"ឧបករណ៍ផ្ទុកមួយចំនួនដែលប្រើដោយ DVR បានបាត់បង់។ សូមភ្ជាប់ថាសផ្ទុកផ្នែកខាងក្រៅដែលអ្នកបានប្រើពីមុន ដើម្បីបើកដំណើរការ DVR ឡើងវិញ ឬអ្នកអាចជ្រើសរើសធ្វើការបំភ្លេចឧបករណ៍ផ្ទុកនេះ ប្រសិនបើវាមិនអាចប្រើបានតទៅទៀត។"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"បំភ្លេចឧបករណ៍ផ្ទុកឬ?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"មាតិកា និងកាលវិភាគដែលបានថតទុករបស់អ្នកទាំងអស់នឹងបាត់បង់។"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"បញ្ឈប់ការថតឬ?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"មាតិកាដែលបានថតនឹងត្រូវបានរក្សាទុក"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"ការថត <xliff:g id="PROGRAMNAME">%1$s</xliff:g> នឹងត្រូវបានបញ្ឈប់ ដោយសារតែវាជាន់ម៉ោងគ្នាជាមួយកម្មវិធីនេះ។ មាតិកាដែលបានថតនេះនឹងត្រូវបានរក្សាទុក។"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ការថតបានកំណត់ពេលហើយ ប៉ុន្តែមានម៉ោងជាន់គ្នា"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ការថតបានចាប់ផ្តើមប៉ុន្តែវាជាន់គ្នា"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> នឹងត្រូវបានថត។"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"កម្មវិធីដូចគ្នានេះត្រូវបានកំណត់ពេលថតរួចហើយនៅម៉ោង <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"បានថតរួចហើយ"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"កម្មវិធីនេះត្រូវបានថតរួចហើយ។ វាអាចប្រើបាននៅក្នុងបណ្ណាល័យ DVR ។"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"បានកំណត់ពេលថតវគ្គ"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ។</item>
+      <item quantity="one">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ។</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ។ ការថតចំនួន <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ក្នុងចំណោមនោះនឹងមិនត្រូវបានថតទេ ដោយសារម៉ោងជាន់គ្នា។</item>
+      <item quantity="one">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ។ វានឹងមិនត្រូវបានថតទេ ដោយសារម៉ោងជាន់គ្នា។</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ។ ភាគចំនួន <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> នៃវគ្គនេះ និងវគ្គផ្សេងទៀតនឹងមិនត្រូវបានថតទេ ដោយសារម៉ោងជាន់គ្នា។</item>
+      <item quantity="one">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ។ ភាគចំនួន <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> នៃវគ្គនេះ និងវគ្គផ្សេងទៀតនឹងមិនត្រូវបានថតទេ ដោយសារម៉ោងជាន់គ្នា។</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ។ ភាគចំនួន 1 នៃវគ្គផ្សេងនឹងមិនត្រូវបានថតទេ ដោយសារម៉ោងជាន់គ្នា។</item>
+      <item quantity="one">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ។ ភាគចំនួន 1 នៃវគ្គផ្សេងនឹងមិនត្រូវបានថតទេ ដោយសារម៉ោងជាន់គ្នា។</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ។ ភាគចំនួន <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> នៃវគ្គផ្សេងនឹងមិនត្រូវបានថតទេ ដោយសារម៉ោងជាន់គ្នា។</item>
+      <item quantity="one">ការថតចំនួន <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ត្រូវបានកំណត់ពេលសម្រាប់ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ។ ភាគចំនួន <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> នៃវគ្គផ្សេងនឹងមិនត្រូវបានថតទេ ដោយសារម៉ោងជាន់គ្នា។</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"រកមិនឃើញកម្មវិធីដែលបានថតទេ"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"ការថតដែលពាក់ព័ន្ធ"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(គ្មានការពិពណ៌នាអំពីកម្មវិធីទេ)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">ការថត %1$d</item>
       <item quantity="one">ការថត %1$d</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"បញ្ឈប់ការថតវគ្គឬ?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"ភាគដែលបានថតនឹងនៅតែមាននៅក្នុងបណ្ណាល័យ DVR ។"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"បញ្ឈប់"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ឥឡូវនេះមិនមានការផ្សាយភាគថ្មីទេ។"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"មិនមានផ្តល់ជូនភាគណាមួយទេ។\nពួកវានឹងត្រូវបានថតបន្ទាប់ពីមានផ្តល់ជូន។"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d នាទី)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ថ្ងៃនេះ"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ថ្ងៃស្អែក"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"ពិន្ទុ"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"កម្មវិធីដែល​បានថត"</string>
 </resources>
diff --git a/res/values-kn-v23/strings.xml b/res/values-kn-rIN-v23/strings.xml
similarity index 100%
rename from res/values-kn-v23/strings.xml
rename to res/values-kn-rIN-v23/strings.xml
diff --git a/res/values-kn/arrays.xml b/res/values-kn-rIN/arrays.xml
similarity index 100%
rename from res/values-kn/arrays.xml
rename to res/values-kn-rIN/arrays.xml
diff --git a/res/values-kn/rating_system_strings.xml b/res/values-kn-rIN/rating_system_strings.xml
similarity index 100%
rename from res/values-kn/rating_system_strings.xml
rename to res/values-kn-rIN/rating_system_strings.xml
diff --git a/res/values-kn/strings.xml b/res/values-kn-rIN/strings.xml
similarity index 75%
rename from res/values-kn/strings.xml
rename to res/values-kn-rIN/strings.xml
index adc9965..28f3395 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"ಮೊನೊ"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ಸ್ಟೀರಿಯೋ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Play ನಿಯಂತ್ರಣಗಳು"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"ಇತ್ತೀಚಿನ ಚಾನಲ್‌ಗಳು"</string>
-    <string name="menu_title_options" msgid="7184594626814914022">"TV ಆಯ್ಕೆಗಳು"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP ಆಯ್ಕೆಗಳು"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ಚಾನಲ್‌ಗಳು"</string>
+    <string name="menu_title_options" msgid="7184594626814914022">"ಟಿವಿ ಆಯ್ಕೆಗಳು"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ಈ ಚಾನಲ್‌ಗೆ ಪ್ಲೇ ನಿಯಂತ್ರಣಗಳು ಲಭ್ಯವಿಲ್ಲ"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"ಪ್ಲೇ ಮಾಡಿ ಅಥವಾ ವಿರಾಮಗೊಳಿಸಿ"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"ವೇಗವಾಗಿ ಮುಂದಕ್ಕೆ"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಗಳು"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"ಪ್ರದರ್ಶನ ಮೋಡ್"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"ಆನ್"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"ಆಫ್"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"ಬಹು-ಆಡಿಯೊ"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"ಹೆಚ್ಚು ಚಾನಲ್‌ ಪಡೆ"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"ಮೂಲ"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"ಸ್ವ್ಯಾಪ್‌ ಮಾಡು"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"ಆನ್"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"ಆಫ್"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ಶಬ್ದ"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"ಪ್ರಮುಖ"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP ವಿಂಡೋ"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"ಲೇಔಟ್"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"ಕೆಳಗಿನ ಬಲಭಾಗ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ಮೇಲಿನ ಬಲಭಾಗ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ಮೇಲಿನ ಎಡಭಾಗ"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"ಕೆಳಗಿನ ಎಡಭಾಗ"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"ಅಕ್ಕ ಪಕ್ಕ"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"ಗಾತ್ರ"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"ದೊಡ್ಡದು"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"ಸಣ್ಣ"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"ಇನ್‌ಪುಟ್ ಮೂಲ"</string>
-    <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (ಆಂಟೆನಾ/ಕೇಬಲ್)"</string>
+    <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ಟಿವಿ (ಆಂಟೆನಾ/ಕೇಬಲ್)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"ಯಾವುದೇ ಕಾರ್ಯಕ್ರಮದ ಮಾಹಿತಿ ಇಲ್ಲ"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"ಯಾವುದೇ ಮಾಹಿತಿ ಇಲ್ಲ"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"ನಿರ್ಬಂಧಿಸಲಾದ ಚಾನಲ್"</string>
-    <string name="default_language" msgid="4122326459624337928">"ಅಪರಿಚಿತ ಭಾಷೆ"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"ಅಪರಿಚಿತ ಭಾಷೆ"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಗಳು %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"ಮುಚ್ಚಿದ ಶೀರ್ಷಿಕೆಗಳು"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"ಆಫ್"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ಫಾರ್ಮ್ಯಾಟ್‌ ಮಾಡುವಿಕೆ ವೈಯಕ್ತೀಕರಿಸಿ"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"ಈ ಪ್ರಕಾರ ಗುಂಪು ಮಾಡಿ"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ರೇಟ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು <xliff:g id="RATING">%1$s</xliff:g> ಎಂದು ರೇಟ್‌ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ಇನ್‌ಪುಟ್ ಸ್ವಯಂ-ಸ್ಕ್ಯಾನ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' ಗಾಗಿ ಸ್ವಯಂ-ಸ್ಕ್ಯಾನ್ ಪ್ರಾರಂಭಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d ಚಾನಲ್‌ಗಳನ್ನು ಸೇರಿಸಲಾಗಿದೆ</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"ಯಾವುದೇ ಚಾನಲ್‌ಗಳನ್ನು ಸೇರಿಸಲಾಗಿಲ್ಲ"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ಟ್ಯೂನರ್"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"ಪೋಷಕ ನಿಯಂತ್ರಣಗಳು"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ಆನ್"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"ಆಫ್"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"ಇತರ ದೇಶಗಳು"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"ಯಾವುದೂ ಇಲ್ಲ"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ಯಾವುದೂ ಇಲ್ಲ"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"ಅನ್‌ರೇಟೆಡ್"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"ರೇಟ್ ಮಾಡದೇ ಇರುವ ಕಾರ್ಯಕ್ರಮಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"ಯಾವುದೂ ಇಲ್ಲ"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"ಅಧಿಕ ನಿರ್ಬಂಧಗಳು"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"ಮಧ್ಯಮ ರೀತಿಯ ನಿರ್ಬಂಧ"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"ಈ ಚಾನಲ್‌ ವೀಕ್ಷಿಸಲು ನಿಮ್ಮ PIN ನಮೂದಿಸಿ"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"ಈ ಕಾರ್ಯಕ್ರಮ ವೀಕ್ಷಿಸಲು ನಿಮ್ಮ PIN ನಮೂದಿಸಿ"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು <xliff:g id="RATING">%1$s</xliff:g> ರೇಟ್ ಮಾಡಲಾಗಿದೆ. ಈ ಕಾರ್ಯಕ್ರಮ ವೀಕ್ಷಿಸಲು ನಿಮ್ಮ ಪಿನ್‌ ನಮೂದಿಸಿ"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ರೇಟ್ ಮಾಡಲಾಗಿಲ್ಲ. ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ವೀಕ್ಷಿಸಲು ನಿಮ್ಮ ಪಿನ್ ನಮೂದಿಸಿ"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"ನಿಮ್ಮ PIN ಅನ್ನು ನಮೂದಿಸಿ"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"ಪೋಷಕ ನಿಯಂತ್ರಣಗಳನ್ನು ಹೊಂದಿಸಲು, PIN ರಚಿಸಿ"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"ಹೊಸ PIN ನಮೂದಿಸಿ"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"ಆ PIN ತಪ್ಪಾಗಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ, PIN ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"ನಿಮ್ಮ ಪಿನ್ ಕೋಡ್ ನಮೂದಿಸಿ."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"ಲೈವ್ ಚಾನಲ್‌ಗಳ ಅಪ್ಲಿಕೇಶನ್ ಟಿವಿ ಚಾನಲ್‌ಗಳಿಗೆ ಸಂಪೂರ್ಣ ಕಾರ್ಯಕ್ರಮ ಮಾರ್ಗದರ್ಶನವನ್ನು ಒದಗಿಸಲು ಪಿನ್ ಕೋಡ್ ಅನ್ನು ಬಳಸುತ್ತದೆ."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"ನಿಮ್ಮ ಪಿನ್ ಕೋಡ್ ನಮೂದಿಸಿ"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"ಅಮಾನ್ಯ ಪಿನ್‌ ಕೋಡ್"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"ಚಾನಲ್‌ಪಟ್ಟಿ ಕಸ್ಟಮೈಸ್‌"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"ನಿಮ್ಮ ಕಾರ್ಯಕ್ರಮ ಸೂಚಿಗಾಗಿ ಚಾನಲ್‌ಗಳನ್ನು ಆರಿಸಿ"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"ಚಾನಲ್ ಮೂಲಗಳು"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"ಹೊಸ ಚಾನಲ್‌ಗಳು ಲಭ್ಯವಿವೆ"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"ಪೋಷಕ ನಿಯಂತ್ರಣಗಳು"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"ಟೈಮ್‌‌ಶಿಫ್ಟ್‌"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"ಲೈವ್ ಕಾರ್ಯಕ್ರಮಗಳನ್ನು ನೋಡುವಾಗ ರೆಕಾರ್ಡ್ ಮಾಡುವುದರಿಂದ ನೀವು ವಿರಾಮ ಅಥವಾ ರಿವೈಂಡ್ ಮಾಡಬಹುದು.\nಎಚ್ಚರಿಕೆ: ಸಂಗ್ರಹಣೆಯ ತೀವ್ರ ಬಳಕೆಯ ಮೂಲಕ ಆಂತರಿಕ ಸಂಗ್ರಹಣೆಯು ಕಡಿಮೆಯಾಗಬಹುದು."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"ಮುಕ್ತ ಮೂಲ ಪರವಾನಗಿಗಳು"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"ಮುಕ್ತ ಮೂಲ ಪರವಾನಗಿಗಳು"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ಪ್ರತಿಕ್ರಿಯೆ ಕಳುಹಿಸಿ"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"ಆವೃತ್ತಿ"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"ಈ ಚಾನಲ್ ಅನ್ನು ವೀಕ್ಷಿಸಲು, ಬಲಕ್ಕೆ ಒತ್ತಿ ಮತ್ತು ನಿಮ್ಮ PIN ಅನ್ನು ನಮೂದಿಸಿ"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ವೀಕ್ಷಿಸಲು, ಬಲಕ್ಕೆ ಒತ್ತಿ ಮತ್ತು ನಿಮ್ಮ PIN ಅನ್ನು ನಮೂದಿಸಿ"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ರೇಟ್ ಮಾಡಲಾಗಿಲ್ಲ.\nಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ವೀಕ್ಷಿಸಲು, ಬಲಭಾಗದಲ್ಲಿ ಒತ್ತಿರಿ ಮತ್ತು ನಿಮ್ಮ ಪಿನ್ ನಮೂದಿಸಿ"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು <xliff:g id="RATING">%1$s</xliff:g> ರೇಟ್ ಮಾಡಲಾಗಿದೆ.\nಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ವೀಕ್ಷಿಸಲು, ಬಲಕ್ಕೆ ಒತ್ತಿ ಮತ್ತು ನಿಮ್ಮ ಪಿನ್ ನಮೂದಿಸಿ."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ಈ ಚಾನಲ್ ವೀಕ್ಷಿಸಲು, ಡಿಫಾಲ್ಟ್ ಲೈವ್ ಟಿವಿ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಿ."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ವೀಕ್ಷಿಸಲು, ಡಿಫಾಲ್ಟ್ ಲೈವ್ ಟಿವಿ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಿ."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ರೇಟ್ ಮಾಡಲಾಗಿಲ್ಲ.\nಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ವೀಕ್ಷಿಸಲು, ಡೀಫಾಲ್ಟ್ ಲೈವ್ ಟಿವಿ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಿ."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು <xliff:g id="RATING">%1$s</xliff:g> ರೇಟ್ ಮಾಡಲಾಗಿದೆ.\nಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ವೀಕ್ಷಿಸಲು, ಡಿಫಾಲ್ಟ್ ಲೈವ್ ಟಿವಿ ಅಪ್ಲಿಕೇಶನ್ ಬಳಸಿ."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"ಕಾರ್ಯಕ್ರಮವನ್ನು ನಿರ್ಬಂಧಿಸಲಾಗಿದೆ"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ರೇಟ್ ಮಾಡಲಾಗಿಲ್ಲ"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು <xliff:g id="RATING">%1$s</xliff:g> ಎಂದು ರೇಟ್‌ ಮಾಡಲಾಗಿದೆ."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ಆಡಿಯೊ ಮಾತ್ರ"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"ದುರ್ಬಲ ಸಿಗ್ನಲ್"</string>
@@ -178,12 +171,10 @@
     <string name="new_sources_action_skip" msgid="2501296961258184330">"ಸರಿ, ಅರ್ಥವಾಯಿತು"</string>
     <!-- no translation found for intro_title (251772896916795556) -->
     <skip />
-    <string name="intro_description" msgid="7806473686446937307">"TV ಮೆನುವನ್ನು ಪ್ರವೇಶಿಸಲು "<b>"ಆಯ್ಕೆ ಮಾಡು ಒತ್ತಿರಿ"</b>"."</string>
-    <string name="msg_no_input" msgid="3897674146985427865">"ಯಾವುದೇ TV ಇನ್‌ಪುಟ್ ಕಂಡುಬಂದಿಲ್ಲ"</string>
-    <string name="msg_no_specific_input" msgid="2688885987104249852">"TV ಇನ್‌ಪುಟ್ ಹುಡುಕಲಾಗಲಿಲ್ಲ"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP ನೊಂದಿಗೆ ತೋರಿಸಬಹುದಾದ ಯಾವುದೇ ಇನ್‌ಪುಟ್ ಲಭ್ಯವಿಲ್ಲ"</string>
-    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ಟ್ಯೂನರ್ ಪ್ರಕಾರವು ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ದಯವಿಟ್ಟು ಟ್ಯೂನರ್ ಪ್ರಕಾರದ TV ಇನ್‌ಪುಟ್‌ಗೆ ಲೈವ್‌ ಚಾನಲ್‌ಗಳ ಅಪ್ಲಿಕೇಶನ್‌ ಪ್ರಾರಂಭಿಸಿ."</string>
+    <string name="intro_description" msgid="7806473686446937307">"ಟಿವಿ ಮೆನುವನ್ನು ಪ್ರವೇಶಿಸಲು "<b>"ಆಯ್ಕೆ ಮಾಡು ಒತ್ತಿರಿ"</b>"."</string>
+    <string name="msg_no_input" msgid="3897674146985427865">"ಯಾವುದೇ ಟಿವಿ ಇನ್‌ಪುಟ್ ಕಂಡುಬಂದಿಲ್ಲ"</string>
+    <string name="msg_no_specific_input" msgid="2688885987104249852">"ಟಿವಿ ಇನ್‌ಪುಟ್ ಹುಡುಕಲಾಗಲಿಲ್ಲ"</string>
+    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ಟ್ಯೂನರ್ ಪ್ರಕಾರವು ಹೊಂದಿಕೆಯಾಗುವುದಿಲ್ಲ. ದಯವಿಟ್ಟು ಟ್ಯೂನರ್ ಪ್ರಕಾರದ ಟಿವಿ ಇನ್‌ಪುಟ್‌ಗೆ ಲೈವ್‌ ಚಾನಲ್‌ಗಳ ಅಪ್ಲಿಕೇಶನ್‌ ಪ್ರಾರಂಭಿಸಿ."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ಟ್ಯೂನ್ ವಿಫಲವಾಗಿದೆ"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ಈ ಕ್ರಿಯೆಯನ್ನು ನಿರ್ವಹಿಸಲು ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ ಕಂಡುಬಂದಿಲ್ಲ."</string>
     <string name="msg_all_channels_hidden" msgid="777397634062471936">"ಎಲ್ಲ ಮೂಲ ಚಾನಲ್‌ಗಳನ್ನು ಮರೆಮಾಡಲಾಗಿದೆ.\nವೀಕ್ಷಿಸಲು ಕನಿಷ್ಠ ಒಂದು ಚಾನಲ್‌‌ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ."</string>
@@ -226,11 +217,13 @@
       <item quantity="one">%1$d ರೆಕಾರ್ಡಿಂಗ್‌ಗಳ ವೇಳಾಪಟ್ಟಿ</item>
       <item quantity="other">%1$d ರೆಕಾರ್ಡಿಂಗ್‌ಗಳ ವೇಳಾಪಟ್ಟಿ</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"ರೆಕಾರ್ಡಿಂಗ್ ರದ್ದುಗೊಳಿಸಿ"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"ರೆಕಾರ್ಡಿಂಗ್ ನಿಲ್ಲಿಸಿ"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ವಾಚ್"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"ಪ್ರಾರಂಭದಿಂದ ಪ್ಲೇ ಮಾಡು"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"ಪ್ಲೇ ಮುಂದುವರಿಸು"</string>
     <string name="dvr_detail_delete" msgid="4535881013528321898">"ಅಳಿಸಿ"</string>
-    <string name="dvr_detail_series_delete" msgid="4831926831670312674">"ರೆಕಾರ್ಡಿಂಗ್‌‌ಗಳನ್ನು ಅಳಿಸು"</string>
+    <string name="dvr_detail_series_delete" msgid="4831926831670312674">"ರೆಕಾರ್ಡಿಂಗ್‌‌ಗಳನ್ನು ಅಳಿಸಿ"</string>
     <string name="dvr_detail_series_resume" msgid="6935136228671386246">"ಮುಂದುವರಿಸು"</string>
     <string name="dvr_detail_series_season_title" msgid="5474850936497854790">"ಸೀಸನ್ <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>"</string>
     <string name="dvr_detail_view_schedule" msgid="7137536927421904426">"ವೇಳಾಪ. ವೀಕ್ಷಿಸಿ"</string>
@@ -258,10 +251,7 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"ಏಕ ಕಾಲದಲ್ಲಿ ರೆಕಾರ್ಡ್‌ ಮಾಡಲು ಸಾಕಷ್ಟು ಕಾರ್ಯಕ್ರಮಗಳು ಇದ್ದ ಸಂದರ್ಭದಲ್ಲಿ, ಹೆಚ್ಚಿನ ಆದ್ಯತೆ ಇರುವುದನ್ನು ಮಾತ್ರ ರೆಕಾರ್ಡ್‌ ಮಾಡಲಾಗುತ್ತದೆ."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"ಉಳಿಸು"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ಒಂದು ಬಾರಿ ಮಾಡಿದ ರೆಕಾರ್ಡಿಂಗ್‌ಗಳು ಹೆಚ್ಚಿನ ಆದ್ಯತೆ ಹೊಂದಿರುತ್ತದೆ"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"ರದ್ದುಮಾಡು"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"ರದ್ದುಮಾಡಿ"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"ಮರೆತುಬಿಡು"</string>
-    <string name="dvr_action_stop" msgid="1378723485295471381">"ನಿಲ್ಲಿಸು"</string>
+    <string name="dvr_action_stop" msgid="1378723485295471381">"ನಿಲ್ಲಿಸಿ"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"ರೆಕಾರ್ಡಿಂಗ್ ವೇಳಾಪಟ್ಟಿ ವೀಕ್ಷಿಸಿ"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"ಈ ಏಕೈಕ ಪ್ರೋಗ್ರಾಂ"</string>
     <string name="dvr_action_record_episode_from_now_description" msgid="5125122951529985697">"ಈಗ - <xliff:g id="ENDTIME">%1$s</xliff:g>"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"ಬದಲಿಗೆ ಇದನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಿ"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ಈ ರೆಕಾರ್ಡಿಂಗ್ ರದ್ದುಗೊಳಿಸಿ"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"ಈಗ ವೀಕ್ಷಿಸಿ"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ರೆಕಾರ್ಡಿಂಗ್‌‌ಗಳನ್ನು ಅಳಿಸಿ..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"ರೆಕಾರ್ಡ್ ಮಾಡಬಹುದಾದ"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ರೆಕಾರ್ಡಿಂಗ್ ನಿಗದಿಪಡಿಸಲಾಗಿದೆ"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ರೆಕಾರ್ಡಿಂಗ್ ಸಂಘರ್ಷ"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"ರೆಕಾರ್ಡ್ ಆಗುತ್ತಿದೆ"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ರೆಕಾರ್ಡಿಂಗ್ ವಿಫಲವಾಗಿದೆ"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"ರೆಕಾರ್ಡಿಂಗ್ ವೇಳಾಪಟ್ಟಿಗಳನ್ನು ರಚಿಸಲು ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ರೀಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ರೀಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ರೀಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"ಇತ್ತೀಚಿನ ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ನ ರೆಕಾರ್ಡಿಂಗ್ ಅಪೂರ್ಣವಾಗಿದೆ."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ಮತ್ತು <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ನ ರೆಕಾರ್ಡಿಂಗ್‌ಗಳು ಅಪೂರ್ಣವಾಗಿವೆ."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ಮತ್ತು <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ನ ರೆಕಾರ್ಡಿಂಗ್‌ಗಳು ಅಪೂರ್ಣವಾಗಿವೆ."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆ ಇಲ್ಲದಿರುವ ಕಾರಣ <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ನ ರೆಕಾರ್ಡಿಂಗ್ ಪೂರ್ಣಗೊಂಡಿಲ್ಲ."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆ ಇಲ್ಲದಿರುವ ಕಾರಣ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ಮತ್ತು <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ನ ರೆಕಾರ್ಡಿಂಗ್‌ಗಳು ಪೂರ್ಣಗೊಂಡಿಲ್ಲ."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆ ಇಲ್ಲದಿರುವ ಕಾರಣ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ಮತ್ತು <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ನ ರೆಕಾರ್ಡಿಂಗ್‌ಗಳು ಪೂರ್ಣಗೊಂಡಿಲ್ಲ."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR ಗೆ ಹೆಚ್ಚಿನ ಸಂಗ್ರಹಣೆಯ ಅಗತ್ಯವಿದೆ"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR ಮೂಲಕ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ. ಅದಾಗ್ಯೂ DVR ಗೆ ಕೆಲಸ ಮಾಡಲು ಇದೀಗ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಸಾಕಷ್ಟು ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ. ದಯವಿಟ್ಟು <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೆಚ್ಚಿನ ಬಾಹ್ಯ ಡ್ರೈವ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಿ ಮತ್ತು ಸಾಧನ ಸಂಗ್ರಹಣೆಯಂತೆ ಫಾರ್ಮ್ಯಾಟ್‌ ಮಾಡಲು ಹಂತಗಳನ್ನು ಅನುಸರಿಸಿ."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR ಮೂಲಕ ಪ್ರೋಗ್ರಾಂಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲು ನಿಮಗೆ ಸಾಧ್ಯವಾಗುತ್ತದೆ. ಅದಾಗ್ಯೂ DVR ಗೆ ಕೆಲಸ ಮಾಡಲು ಇದೀಗ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಸಾಕಷ್ಟು ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ. ದಯವಿಟ್ಟು <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB ಅಥವಾ ಅದಕ್ಕಿಂತ ಹೆಚ್ಚಿನ ಬಾಹ್ಯ ಡ್ರೈವ್‌ಗೆ ಸಂಪರ್ಕಿಸಿ ಮತ್ತು ಸಾಧನ ಸಂಗ್ರಹಣೆಯಂತೆ ಫಾರ್ಮ್ಯಾಟ್‌ ಮಾಡಲು ಹಂತಗಳನ್ನು ಅನುಸರಿಸಿ."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆಯಿಲ್ಲ"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"ಸಾಕಷ್ಟು ಸಂಗ್ರಹಣೆ ಇಲ್ಲದಿರುವ ಕಾರಣ ಈ ಕಾರ್ಯಕ್ರಮವನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ. ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಕೆಲವು ರೆಕಾರ್ಡಿಂಗ್ ಅಳಿಸಲು ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"ಸಂಗ್ರಹಣೆ ಕಾಣೆಯಾಗಿದೆ"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR ಮೂಲಕ ಬಳಸಲಾದ ಕೆಲವು ಸಂಗ್ರಹಣೆಯು ಕಾಣೆಯಾಗಿದೆ. ನೀವು DVR ಮರು-ಸಕ್ರಿಯಗೊಳಿಸುವ ಮೊದಲು ಬಳಸಲಾದ ಬಾಹ್ಯ ಡ್ರೈವ್ ಅನ್ನು ಸಂಪರ್ಕಪಡಿಸಿ. ಪರ್ಯಾಯವಾಗಿ, ಇನ್ನೂ ಮುಂದೆ ಲಭ್ಯವಿಲ್ಲದಿದ್ದರೆ ಸಂಗ್ರಹಣೆಯನ್ನು ಮರೆಯಲು ನೀವು ಆಯ್ಕೆಮಾಡಬಹುದು."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"ಸಂಗ್ರಹಣೆಯನ್ನು ಮರೆತಿರುವಿರಾ?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"ನಿಮ್ಮ ಎಲ್ಲಾ ರೆಕಾರ್ಡ್ ಮಾಡಲಾದ ವಿಷಯ ಮತ್ತು ವೇಳಾಪಟ್ಟಿಗಳು ಕಳೆದುಹೋಗುತ್ತವೆ."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"ರೆಕಾರ್ಡಿಂಗ್ ನಿಲ್ಲಿಸುವುದೇ?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"ರೆಕಾರ್ಡ್‌ ಮಾಡಲಾದ ವಿಷಯವನ್ನು ಉಳಿಸಲಾಗುತ್ತದೆ."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"ಈ ಕಾರ್ಯಕ್ರಮದ ಜೊತೆಗೆ ರೆಕಾರ್ಡಿಂಗ್ ಸಂಘರ್ಷಿಸುವ ಕಾರಣದಿಂದಾಗಿ <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ರೆಕಾರ್ಡಿಂಗ್ ಅನ್ನು ನಿಲ್ಲಿಸಲಾಗುವುದು. ರೆಕಾರ್ಡ್ ಮಾಡಲಾದ ವಿಷಯವನ್ನು ಉಳಿಸಲಾಗುವುದು."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ರೆಕಾರ್ಡಿಂಗ್ ನಿಗದಿಪಡಿಸಲಾಗಿದೆ ಆದರೆ ಸಂಘರ್ಷಣೆಗಳನ್ನು ಹೊಂದಿದೆ"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸಲಾಗಿದೆ ಆದರೆ ಸಂಘರ್ಷಣೆಗಳನ್ನು ಹೊಂದಿದೆ"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ಅನ್ನು ರೆಕಾರ್ಡ್‌ ಮಾಡಲಾಗುತ್ತದೆ."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"ಅದೇ ಕಾರ್ಯಕ್ರಮವನ್ನು ಈಗಾಗಲೇ <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> ಸಮಯಕ್ಕೆ ರೆಕಾರ್ಡ್ ಮಾಡಲು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"ಈಗಾಗಲೇ ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"ಈ ಪ್ರೋಗ್ರಾಂ ಅನ್ನು ಈಗಾಗಲೇ ರೆಕಾರ್ಡ್‌ ಮಾಡಲಾಗಿದೆ. ಇದು DVR ಲೈಬ್ರರಿಯಲ್ಲಿ ಲಭ್ಯವಿದೆ."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"ಸರಣಿ ರೆಕಾರ್ಡಿಂಗ್ ನಿಗದಿಪಡಿಸಲಾಗಿದೆ"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ. ಸಂಘರ್ಷಗಳ ಕಾರಣದಿಂದಾಗಿ ಅವುಗಳಲ್ಲಿ <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ. ಸಂಘರ್ಷಗಳ ಕಾರಣದಿಂದಾಗಿ ಅವುಗಳಲ್ಲಿ <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ಅನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ. ಸಂಘರ್ಷಗಳ ಕಾರಣದಿಂದಾಗಿ ಈ ಸರಣಿಯ ಮತ್ತು ಇತರ ಸರಣಿಯ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ಸಂಚಿಕೆಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ. ಸಂಘರ್ಷಗಳ ಕಾರಣದಿಂದಾಗಿ ಈ ಸರಣಿಯ ಮತ್ತು ಇತರ ಸರಣಿಯ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ಸಂಚಿಕೆಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ. ಸಂಘರ್ಷಗಳ ಕಾರಣದಿಂದಾಗಿ ಇತರ ಸರಣಿಯ 1 ಸಂಚಿಕೆಯನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ. ಸಂಘರ್ಷಗಳ ಕಾರಣದಿಂದಾಗಿ ಇತರ ಸರಣಿಯ 1 ಸಂಚಿಕೆಯನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ. ಸಂಘರ್ಷಗಳ ಕಾರಣದಿಂದಾಗಿ ಇತರ ಸರಣಿಯ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ಸಂಚಿಕೆಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> ಗೆ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ರೆಕಾರ್ಡಿಂಗ್‌ಗಳನ್ನು ನಿಗದಿಪಡಿಸಲಾಗಿದೆ. ಸಂಘರ್ಷಗಳ ಕಾರಣದಿಂದಾಗಿ ಇತರ ಸರಣಿಯ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ಸಂಚಿಕೆಗಳನ್ನು ರೆಕಾರ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"ರೆಕಾರ್ಡ್‌ ಮಾಡಲಾದ ಕಾರ್ಯಕ್ರಮ ಕಂಡುಬಂದಿಲ್ಲ."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"ಸಂಬಂಧಿಸಿದ ರೆಕಾರ್ಡಿಂಗ್‌ಗಳು"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(ಯಾವುದೇ ಪ್ರೋಗ್ರಾಂ ವಿವರಣೆಯಿಲ್ಲ)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d ರೆಕಾರ್ಡಿಂಗ್‌ಗಳು</item>
       <item quantity="other">%1$d ರೆಕಾರ್ಡಿಂಗ್‌ಗಳು</item>
@@ -332,10 +337,11 @@
     </plurals>
     <string name="dvr_series_schedules_settings" msgid="4868501926847903985">"ಸರಣಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="dvr_series_schedules_start" msgid="8458768834047133835">"ಸರಣಿ ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭ"</string>
-    <string name="dvr_series_schedules_stop" msgid="3427479298317584961">"ಸರಣಿ ರೆಕಾರ್ಡಿಂಗ್ ನಿಲ್ಲಿಸು"</string>
+    <string name="dvr_series_schedules_stop" msgid="3427479298317584961">"ಸರಣಿ ರೆಕಾರ್ಡಿಂಗ್ ನಿಲ್ಲಿಸಿ"</string>
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"ಸರಣಿ ರೆಕಾರ್ಡಿಂಗ್ ನಿಲ್ಲಿಸುವುದೇ?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"ರೆಕಾರ್ಡ್‌ ಮಾಡಲಾದ ಭಾಗಗಳು DVR ಲೈಬ್ರರಿಯಲ್ಲಿ ಲಭ್ಯವಿರುತ್ತವೆ."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"ನಿಲ್ಲಿಸಿ"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ಈಗ ಪ್ರಸಾರ ಮಾಡಲು ಯಾವುದೇ ಸಂಚಿಕೆಗಳಿಲ್ಲ."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"ಯಾವುದೇ ಸಂಚಿಕೆಗಳು ಲಭ್ಯವಿಲ್ಲ.\nಅವುಗಳು ಒಮ್ಮೆ ಲಭ್ಯವಾದಾಗ ಅವುಗಳನ್ನು ರೆಕಾರ್ಡ್‌ ಮಾಡಲಾಗುತ್ತದೆ."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d ನಿಮಿಷಗಳು)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ಇಂದು"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ನಾಳೆ"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"ಸ್ಕೋರ್"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"ರೆಕಾರ್ಡ್ ಮಾಡಲಾದ ಪ್ರೋಗ್ರಾಂಗಳು"</string>
 </resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 4e9fa6a..de25fd9 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"모노"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"스테레오"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"재생 컨트롤"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"최근 시청한 채널"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"채널"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV 옵션"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP 옵션"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"이 채널에서 재생 컨트롤을 사용할 수 없습니다."</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"재생 또는 일시중지"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"빨리 감기"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"자막"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"표시 모드"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"사용"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"사용 안함"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"멀티 오디오"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"채널 더보기"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"설정"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"소스"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"전환"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"사용"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"사용 안함"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"소리"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"기본"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP 창"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"레이아웃"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"오른쪽 하단"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"오른쪽 상단"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"왼쪽 상단"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"왼쪽 하단"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"나란히"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"크기"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"크게"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"작게"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"입력 소스"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV(안테나/케이블)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"프로그램 정보가 없습니다."</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"정보 없음"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"차단된 채널"</string>
-    <string name="default_language" msgid="4122326459624337928">"알 수 없는 언어"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"알 수 없는 언어"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"%1$d 자막"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"자막"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"사용 안함"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"포맷 맞춤설정"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"그룹 기준"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"프로그램이 차단되었습니다."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"등급이 없는 프로그램입니다."</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"이 프로그램의 시청 등급은 <xliff:g id="RATING">%1$s</xliff:g>입니다."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"입력이 자동 스캔을 지원하지 않습니다."</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\'의 자동 스캔을 시작할 수 없습니다."</string>
@@ -92,7 +74,6 @@
       <item quantity="one">채널 %1$d개 추가됨</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"추가된 채널 없음"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"튜너"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"자녀 보호 기능"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"사용"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"사용 안함"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"기타 국가"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"없음"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"없음"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"등급 없음"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"등급이 없는 프로그램 차단"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"없음"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"높은 제한"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"중간 제한"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"PIN을 입력하여 이 채널 시청"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"PIN을 입력하여 이 프로그램 시청"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"이 프로그램의 등급은 <xliff:g id="RATING">%1$s</xliff:g>입니다. 이 프로그램을 감상하려면 PIN을 입력하세요."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"등급이 없는 프로그램입니다. 프로그램을 시청하려면 PIN을 입력하세요."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PIN 입력"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"PIN을 생성하여 자녀 보호 기능 설정"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"새 PIN 입력"</string>
@@ -137,22 +121,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN이 잘못되었습니다. 다시 시도해 주세요."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"다시 시도해 주세요. PIN이 일치하지 않습니다."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"우편번호 입력"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"실시간 채널 앱에서 TV 채널에 관한 전체 프로그램 가이드를 제공하는 데 우편번호가 사용됩니다."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"우편번호를 입력하세요."</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"잘못된 우편번호입니다."</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"설정"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"채널 목록 맞춤설정"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"프로그램 가이드용 채널을 선택합니다."</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"채널 소스"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"새 채널 사용 가능"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"자녀 보호 기능"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"타임시프트"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"생방송 프로그램을 일시중지하거나 되감을 수 있도록 시청하면서 녹화해 보세요.\n경고: 이 기능을 사용하면 저장소가 많이 사용되므로 내부 저장소 수명이 줄어들 수도 있습니다."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"오픈소스 라이선스"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"오픈소스 라이선스"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"의견 보내기"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"버전"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"이 채널을 보려면 오른쪽을 누르고 PIN을 입력하세요."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"이 프로그램을 보려면 오른쪽을 누르고 PIN을 입력하세요."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"등급이 없는 프로그램입니다.\n프로그램을 시청하려면 오른쪽을 누르고 PIN을 입력하세요."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"이 프로그램의 시청 등급은 <xliff:g id="RATING">%1$s</xliff:g>입니다.\n이 프로그램을 보려면 오른쪽을 누르고 PIN을 입력하세요."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"이 채널을 감상하려면 기본 실시간 TV 앱을 사용합니다."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"이 프로그램을 감상하려면 기본 실시간 TV 앱을 사용합니다."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"등급이 없는 프로그램입니다.\n프로그램을 시청하려면 기본 실시간 TV 앱을 사용하세요."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"이 프로그램의 등급은 <xliff:g id="RATING">%1$s</xliff:g>입니다.\n이 프로그램을 감상하려면 기본 실시간 TV 앱을 사용합니다."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"차단된 프로그램입니다."</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"등급이 없는 프로그램입니다."</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"이 프로그램의 시청 등급은 <xliff:g id="RATING">%1$s</xliff:g>입니다."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"오디오 전용"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"신호 약함"</string>
@@ -183,8 +176,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"선택을 눌러"</b>" TV 메뉴에 액세스합니다."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"TV 입력이 없습니다."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV 입력을 찾을 수 없습니다."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP가 지원되지 않습니다."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP로 표시할 수 있는 입력이 없습니다."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"튜너 유형이 적합하지 않습니다. 튜너 유형 TV 입력에 실시간 채널 앱을 실행하세요."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"조정에 실패했습니다."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"이 작업을 처리하는 앱을 찾을 수 없습니다."</string>
@@ -228,6 +219,8 @@
       <item quantity="other">예약된 녹화 %1$d개</item>
       <item quantity="one">예약된 녹화 %1$d개</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"녹화 취소"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"녹화 중지"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"시계"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"처음부터 재생"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"이어서 보기"</string>
@@ -260,9 +253,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"동시에 녹화해야 하는 프로그램이 너무 많은 경우 우선순위가 높은 프로그램만 녹화됩니다."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"저장"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"일회 녹화의 우선순위가 가장 높음"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"취소"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"취소"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"삭제"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"중지"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"녹화 일정 보기"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"이 프로그램만"</string>
@@ -272,25 +262,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"대신 이 항목을 녹화하기"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"이 녹화 취소하기"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"지금 보기"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"녹화된 프로그램 삭제 중..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"녹화 가능"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"녹화 예약됨"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"녹화 예약 충돌"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"녹화 중"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"녹화 실패"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"프로그램을 확인하고 녹화 일정을 만듭니다."</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"프로그램 정보 읽는 중"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"프로그램 정보 읽는 중"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"최근 녹화 보기"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> 녹화를 완료하지 못했습니다."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> 녹화를 완료하지 못했습니다."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> 녹화를 완료하지 못했습니다."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"저장용량이 부족하여 <xliff:g id="PROGRAMNAME">%1$s</xliff:g> 녹화를 완료하지 못했습니다."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"저장용량이 부족하여 <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> 녹화를 완료하지 못했습니다."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"저장용량이 부족하여 <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> 녹화를 완료하지 못했습니다."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR에 저장용량이 더 필요합니다."</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR을 사용하여 프로그램을 녹화할 수 있습니다. 그러나 DVR을 사용하기에는 기기에 남아있는 저장용량이 충분하지 않습니다. <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB 이상의 외부 드라이브를 연결하고 외부 드라이브를 기기 저장소로 포맷하기 위한 단계를 따르세요."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR을 사용하여 프로그램을 녹화할 수 있습니다. 그러나 DVR을 사용하기에는 기기에 남아있는 저장용량이 충분하지 않습니다. <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB 이상의 외부 드라이브를 연결하고 외부 드라이브를 기기 저장소로 포맷하기 위한 단계를 따르세요."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"저장공간 부족"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"저장용량이 부족하여 이 프로그램을 녹화할 수 없습니다. 기존 녹화 프로그램 일부를 삭제해 주세요."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"저장소 없음"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR에 사용되던 일부 저장소가 없습니다. 사용하던 외부 드라이브를 연결한 다음 DVR을 다시 사용 설정하시기 바랍니다. 또는 저장소를 더 이상 사용할 수 없는 경우 삭제할 수 있습니다."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"저장소를 삭제하시겠습니까?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"기록된 모든 콘텐츠 및 일정이 삭제됩니다."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"녹화를 중지하시겠습니까?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"녹화된 콘텐츠가 저장됩니다."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> 녹화가 이 프로그램과 충돌하여 중지됩니다. 녹화된 콘텐츠는 저장됩니다."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"녹화가 예약되었으나 충돌이 있음"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"녹화가 시작되었으나 충돌이 있음"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>이(가) 녹화됩니다."</string>
@@ -308,17 +301,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"동일한 프로그램이 이미 <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>에 녹화 예약되었습니다."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"이미 녹화됨"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"이 프로그램이 이미 녹화되었습니다. DVR 라이브러리에서 사용할 수 있습니다."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"시리즈 녹화 예약됨"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>개가 예약되었습니다.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>개가 예약되었습니다.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>개가 예약되었습니다. 충돌이 발생하여 이 중 <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>개는 녹화되지 않습니다.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>개가 예약되었습니다. 충돌이 발생하여 녹화되지 않습니다.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>개가 예약되었습니다. 충돌이 발생하여 이 시리즈 및 다른 시리즈의 에피소드 <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>개는 녹화되지 않습니다.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>개가 예약되었습니다. 충돌이 발생하여 이 시리즈 및 다른 시리즈의 에피소드 <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g>개는 녹화되지 않습니다.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>개가 예약되었습니다. 충돌이 발생하여 다른 시리즈의 에피소드 1개는 녹화되지 않습니다.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>개가 예약되었습니다. 충돌이 발생하여 다른 시리즈의 에피소드 1개는 녹화되지 않습니다.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>개가 예약되었습니다. 충돌이 발생하여 다른 시리즈의 에피소드 <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>개는 녹화되지 않습니다.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> 녹화 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g>개가 예약되었습니다. 충돌이 발생하여 다른 시리즈의 에피소드 <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g>개는 녹화되지 않습니다.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"녹화된 프로그램을 찾을 수 없습니다."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"관련 녹화"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(프로그램 설명 없음)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">녹화 %1$d개</item>
       <item quantity="one">녹화 %1$d개</item>
@@ -338,6 +343,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"시리즈 녹화를 중지하시겠습니까?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"녹화된 에피소드는 DVR 라이브러리에서 계속 사용할 수 있습니다."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"중지"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"현재 방송 중인 에피소드가 없습니다."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"사용할 수 있는 에피소드가 없습니다.\n사용 가능한 에피소드가 생기면 녹화됩니다."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d분)</item>
@@ -349,4 +355,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"오늘 <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"내일 <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"점수"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"녹화된 프로그램"</string>
 </resources>
diff --git a/res/values-ky-v23/strings.xml b/res/values-ky-rKG-v23/strings.xml
similarity index 100%
rename from res/values-ky-v23/strings.xml
rename to res/values-ky-rKG-v23/strings.xml
diff --git a/res/values-ky/arrays.xml b/res/values-ky-rKG/arrays.xml
similarity index 100%
rename from res/values-ky/arrays.xml
rename to res/values-ky-rKG/arrays.xml
diff --git a/res/values-ky/rating_system_strings.xml b/res/values-ky-rKG/rating_system_strings.xml
similarity index 100%
rename from res/values-ky/rating_system_strings.xml
rename to res/values-ky-rKG/rating_system_strings.xml
diff --git a/res/values-ky/strings.xml b/res/values-ky-rKG/strings.xml
similarity index 77%
rename from res/values-ky/strings.xml
rename to res/values-ky-rKG/strings.xml
index 2b9d37a..088bc63 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"моно"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"стерео"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Ойнотууну башкаруу"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Акыркы каналдар"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Каналдар"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Сынлг прметрлр"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP параметрлери"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Бул канал үчүн ойнотуу көзөмөлдөрү жеткиликтүү эмес"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Ойнотуу же тындыруу"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Алдыга түрүү"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Жабык субттрлр"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Көрсөтүү режими"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Күйүк"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Өчүк"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Мульти-аудио"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Дагы канлдрд алуу"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Жөндөөлөр"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Булак"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Алмаштыруу"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Күйүк"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Өчүк"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Үн"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Негизги"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP терезеси"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Үлгү"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Төмөнкү оң"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Жогорку оң"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Жогорку сол"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Төмөнкү сол"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Тушма-туш"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Өлчөмү"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Чоң"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Кичине"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Киргизүү булагы"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Сыналгы (антенна/кабель)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Программанын маалыматы жок"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Маалымат жок"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Бөгөттөлгөн канал"</string>
-    <string name="default_language" msgid="4122326459624337928">"Белгисиз тил"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Белгисиз тил"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Коштомо жазуулар %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Коштомо жазуулар"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Өчүк"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Формттоону өзгөчөлшт"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Топ"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Бул программа бөгөттөлгөн."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Бул программанын рейтинги жок"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Бул программанын рейтинги <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Киргизмеде авто-скан колдоого алынбайт"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\"<xliff:g id="TV_INPUT">%s</xliff:g>\" үчүн авто издөөнү баштай албайт"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d канал кошулду</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Каналдар кошулган жок"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Жөндөгүч"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Ата-энелик көзөмөл"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Күйүк"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Өчүк"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Башка өлкөлөр"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Эч бири"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Эч бири"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Рейтинги жок"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Рейтинги жок программалар бөгөттөлсүн"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Эч бири"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Катаал чектөөлөр"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Орточо чектөөлөр"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Бул каналды көрүү үчүн PIN\'иңизди киргизиңиз"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Бул программаны көрүү үчүн PIN\'иңизди киргизиңиз"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Бул программанын рейтинги <xliff:g id="RATING">%1$s</xliff:g>. Бул программаны көрүү үчүн PIN\'ди киргизиңиз"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Бул программанын рейтинги жок. Бул программаны көрүү үчүн PIN кодуңузду киргизиңиз"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PIN\'иңизди киргизиңиз"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Ата-энелер көзөмөлүн коюу үчүн, PIN код түзүңүз"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Жаңы PIN киргизиңиз"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Ал PIN туура эмес. Дагы бир жолу киргизиңиз."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN дал келбей жатат, дагы бир жолу аракет кылыңыз"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Почтаңыздын индексин киргизиңиз."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Түз ободогу каналдар колдонмосу сыналгы каналдары боюнча программалардын толук тизмесин түзүү үчүн почта индексин пайдаланат."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Почтаңыздын индексин киргизиңиз"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Почта индекси жараксыз"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Жөндөөлөр"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Канал тизмесин ыңгайлаштыруу"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Программа жетегиңиз үчүн каналдарды тандаңыз"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Канал булактары"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Жаңы каналдар бар"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Ата-эненин көзөмөлү"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Убакытты жылдыруу"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Түз ободогу программаларды тындыруу жана артка түрүү үчүн, аларды көрүп жатканда, жаздырып алыңыз.\nЭскертүү: Бул функция сактагычты көп пайдалангандыктан, ички сактагычтын иштөө мөөнөтүн азайтышы мүмкүн."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Ачык программа уруксаттамалары"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Ачык программа уруксаттамалары"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Пикир билдирүү"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Версиясы"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Бул каналды көрүү үчүн, Оңго басып, PIN-иңизди киргизиңиз"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Бул программаны көрүү үчүн, Оңго басып, PIN-иңизди киргизиңиз"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Бул программанын рейтинги жок.\nБул программаны көрүү үчүн баскычтоптогу Оң жебени басып туруп, PIN кодуңузду киргизиңиз"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Бул программанын рейтинги <xliff:g id="RATING">%1$s</xliff:g> \n Бул программаны көрүү үчүн, Оң баскычын басып, PIN\'иңизди киргизиңиз"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Бул каналды көрүү үчүн демейки Түз ободогу сыналгы колдонмосун пайдаланыңыз."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Бул программаны көрүү үчүн демейки Түз ободогу сыналгы колдонмосун пайдаланыңыз."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Бул программанын рейтинги жок.\nБул программаны көрүү үчүн демейки Түз обо TV колдонмосун пайдаланыңыз."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Бул программанын рейтинги <xliff:g id="RATING">%1$s</xliff:g>.\nБул программаны көрүү үчүн демейки Түз ободогу сыналгы колдонмосун пайдаланыңыз."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Бул программа бөгөттөлгөн"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Бул программанын рейтинги жок"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Бул программанын рейтинги –  <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Аудио гана"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Начар сигнал"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"Сыналгынын менюсун ачуу үчүн "<b>"ТАНДОО"</b>" баскычын басыңыз."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Сыналгыга киргизме табылган жок"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Сыналгыга киргизме табылбай жатат"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP колдоого алынбайт"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP аркылуу көрсөтүлө турган эч нерсе киргизилген жок."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Тюнердин түрү ылайыксыз. Тюнердин түрүндөгү сыналгы киргизмеси үчүн Жандуу каналдар колдонмосун ишке киргизиңиз."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Жөндөлбөй калды"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Бул ишти аткара турган бир дагы колдонмо табылган жок."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d жаздыруу ыраатталган</item>
       <item quantity="one">%1$d жаздыруу ыраатталган</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Жаздырууну жокко чыгаруу"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Жаздырууну токтотуу"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Саат"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Башынан баштап ойнотуу"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Ойнотууну улантуу"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Бир эле убакта жаздыра турган программалардын саны өтө көп болгон учурда, эң жогорку артыкчылыгы барлары гана жаздырылат."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Сактоо"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Бир жолку жаздыруулар жогорку артыкчылыкка ээ болот"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Баш тартуу"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Жокко чыгаруу"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Унутуу"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Токтотуу"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Жаздыруу графигин көрүү"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Жалгыз ушул программа"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Анын ордуна бул жаздырылсын"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Бул жаздыруу жокко чыгарылсын"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Азыр көрүңүз"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Жаздырылган көрсөтүүлөрдү өчүрүү"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Жаздырууга болот"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Пландаштырылган жаздыруу"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Жаздырууда дал келбестик бар"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Жаздырууда"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Жаздырылбай калды"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Ырааттамаларды жаздырууну түзүү үчүн программаларды окуу"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Программалар окулууда"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Программалар окулууда"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Акыркы жаздырууларды көрүңүз"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> жаздырылып бүтпөй калды."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> жана <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> жаздырылып бүтпөй калды."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> жана <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> жаздырылып бүтпөй калды."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Сактагычта орун жетишсиз болгондуктан <xliff:g id="PROGRAMNAME">%1$s</xliff:g> жаздырылып бүтпөй калды."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Сактагычта орун жетишсиз болгондуктан <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> жана <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> жаздырылып бүтпөй калды."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Сактагычта орун жетишсиз болгондуктан <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> жана <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> жаздырылып бүтпөй калды."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR көбүрөөк орунду талап кылат"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Сиз DVR менен программаларды жаздыра аласыз. Бирок, DVR\'ды иштетүү үчүн түзмөгүңүздө бош орун калбай калды. Көлөмү <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>Гб же андан ашык болгон тышкы драйверге туташыңыз да, аны түзмөктүн сактагычы катары жөндөп алыңыз."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Сиз DVR менен программаларды жаздыра аласыз. Бирок, DVR\'ды иштетүү үчүн түзмөгүңүздө бош орун калбай калды. Көлөмү <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>Гб же андан ашык болгон тышкы драйверге туташыңыз да, аны түзмөктүн сактагычы катары жөндөп алыңыз."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Сактагычта орун жетишсиз"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Сактагычта орун жетишсиз болгондуктан, бул көрсөтүү жаздырылбайт. Мурда жаздырылган көрсөтүүлөрдү өчүрүп көрүңүз."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Сактагыч жок болуп жатат"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR колдонгон сактагычтын айрым бөлүмдөрү жок болуп жатат. DVR\'ды кайра иштетүү үчүн колдонулган тышкы драйверди туташтырыңыз. Же болбосо, жеткиликсиз сактагыч унутулсун дегенди тандасаңыз болот."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Сактагыч унутулсунбу?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Бардык жаздырылган мазмун жана графиктериңиз жоголот."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Жаздыруу токтотулсунбу?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Тартылган мазмун сакталып калат."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Убакыты бул программаныкына дал келип калгандыктан <xliff:g id="PROGRAMNAME">%1$s</xliff:g> жаздыруусу токтотулат. Жаздырылган мазмун сакталып калат."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Пландаштырылган жаздыруу, бирок бир убакытка коюлуп калган"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Жаздыруу башталды, бирок башка программа менен дал келип калган"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> жаздырылат."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Ушул эле программа буга чейин <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> жаздыруу графигине кошулган."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Буга чейин жаздырылган"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Бул программа буга чейин жазылган. Ал DVR китепканасында жеткиликтүү."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Сериалдын жаздыруусу пландаштырылды"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> жолу жаздыруу пландаштырылган.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жолу жаздыруу пландаштырылган.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> жолу жаздыруу пландаштырылган. Убакыттары дал келип калгандыктан, алардын <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> сериясы жаздырылбайт.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жолу жаздыруу пландаштырылган. Убакыты дал келип калгандыктан, ал жаздырылбайт.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> жолу жаздыруу пландаштырылган. Убакыттары дал келип калгандыктан, бул сериалдын <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> сериясы жана башка сериал жаздырылбайт.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жолу жаздыруу пландаштырылган. Убакыттары дал келип калгандыктан, бул сериалдын <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> сериясы жана башка сериал жаздырылбайт.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> жолу жаздыруу пландаштырылган. Убакыттары дал келип калгандыктан, башка сериалдын 1 сериясы жаздырылбайт.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жолу жаздыруу пландаштырылган. Убакыттары дал келип калгандыктан, башка сериалдын 1 сериясы жаздырылбайт.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> жолу жаздыруу пландаштырылган. Убакыттары дал келип калгандыктан, башка сериалдын <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> сериясы жаздырылбайт.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> сериалын <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> жолу жаздыруу пландаштырылган. Убакыттары дал келип калгандыктан, башка сериалдын <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> сериясы жаздырылбайт.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Жаздырылган программа табылган жок."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Окшош жаздыруулар"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Программанын сүрөттөлүшү жок)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d жаздыруу</item>
       <item quantity="one">%1$d жаздыруу</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Сериал тартуу токтотулсунбу?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Тартылган сериялар DVR китепканасында сакталып калат."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Токтотуу"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Азыр эч кандай серия көрсөтүлбөй турат"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Учурда бир да эпизод жок.\nАлар жеткиликтүү болоору менен жаздырылат."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d мүнөт)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Бүгүн саат <xliff:g id="TIME_RANGE">%1$s</xliff:g> чейин"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Эртең саат <xliff:g id="TIME_RANGE">%1$s</xliff:g> чейин"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Упай"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Жаздырылган программалар"</string>
 </resources>
diff --git a/res/values-ldrtl/dimens.xml b/res/values-ldrtl/dimens.xml
index 0b79b14..4b030d4 100644
--- a/res/values-ldrtl/dimens.xml
+++ b/res/values-ldrtl/dimens.xml
@@ -28,7 +28,6 @@
     <dimen name="program_guide_table_background_round_radius_right">2dp</dimen>
 
     <dimen name="program_guide_shift_start_to_end_x">-238dp</dimen>
-    <dimen name="program_guide_shift_end_to_start_x">238dp</dimen>
     <dimen name="program_guide_side_panel_row_pivot_x">
         @dimen/program_guide_side_panel_item_width</dimen>
     <dimen name="program_guide_side_panel_exit_x">32dp</dimen>
diff --git a/res/values-lo-v23/strings.xml b/res/values-lo-rLA-v23/strings.xml
similarity index 100%
rename from res/values-lo-v23/strings.xml
rename to res/values-lo-rLA-v23/strings.xml
diff --git a/res/values-lo/arrays.xml b/res/values-lo-rLA/arrays.xml
similarity index 100%
rename from res/values-lo/arrays.xml
rename to res/values-lo-rLA/arrays.xml
diff --git a/res/values-lo/rating_system_strings.xml b/res/values-lo-rLA/rating_system_strings.xml
similarity index 100%
rename from res/values-lo/rating_system_strings.xml
rename to res/values-lo-rLA/rating_system_strings.xml
diff --git a/res/values-lo/strings.xml b/res/values-lo-rLA/strings.xml
similarity index 78%
rename from res/values-lo/strings.xml
rename to res/values-lo-rLA/strings.xml
index 05aba1c..06bb63a 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"​ໂມ​ໂນ"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ສະ​ເຕ​ຣິ​ໂອ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"ຄວບ​ຄຸມ​ການ​ຫຼິ້ນ"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"ຊ່ອງ​ບໍ່ດົນ​ມານີ້"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"​ຊ່ອງ"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"ໂຕເລືອກ​ໂທລະພາບ"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"​ຕົວ​ເລືອກ PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ຫຼິ້ນ​ການ​ຄວບ​ຄຸມ​ບໍ່​ມີ​ໃຫ້​ສຳ​ລັບ​ຊ່ອງ​ນີ້"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"ຫຼິ້ນ​ ຫລື​ຢຸດ​ຊົ່ວ​ຄາວ"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"ເລື່ອນ​ໄປ​ໜ້າ"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"ຄຳ​ບັນຍາຍ​ແບບ​ປິດ"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"ໂໝດ​ການ​ສະແດງຜົນ"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"​ເປີດ"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"ປິດ"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"ຫຼາຍສຽງ"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"ເອົາຊ່ອງເພີ່ມເຕີມ"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"ການ​ຕັ້ງ​ຄ່າ"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"ທີ່​ມາ"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"ສະຫຼັບ"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"​ເປີດ"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"ປິດ"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ສຽງ"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"ຫຼັກ"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"ໜ້າ​ຕ່າງ PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"ຮູບ​ແບບ"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"ເບື້ອງ​ຂວາ​ທາງ​ລຸ່ມ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ເບື້ອງ​ຂວາ​ດ້ານ​ເທິງ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ເບື້ອງ​ຊ້າຍ​ດ້ານ​ເທິງ"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"ເບື້ອງ​ຊ້າຍທາງ​ລຸ່ມ"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"ເທື່ອ​ລະ​ດ້ານ"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"ຂະໜາດ"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"ໃຫຍ່"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"ນ້ອຍ"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"​ແຫຼ່ງ​ສັນ​ຍານ"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (ເສົາ​ສັນ​ຍານ/ສາຍ​ເຄ​ເບິນ)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"ບໍ່​ມີ​ຂໍ້​ມູນ​ລາຍ​ການ"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"ບໍ່ມີຂໍ້ມູນ"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"ຊ່ອງ​ທີ່​ຖືກບ​ລັອກ"</string>
-    <string name="default_language" msgid="4122326459624337928">"ພາ​ສາ​ບໍ່​ຮູ້​ຈັກ"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"ພາ​ສາ​ບໍ່​ຮູ້​ຈັກ"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"ຄຳບັນຍາຍ %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"ຄຳ​ບັນຍາຍ​ແບບ​ປິດ"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"ປິດ"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ປັບແຕ່ງການຈັດຮູບແບບ"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"ຈັດກຸ່ມຕາມ"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"ໂປ​ຣ​ແກ​ຣມ​ນີ້​ຖືກບ​ລັອກ​ແລ້ວ"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"ລາຍການນີ້ບໍ່ໄດ້ຈັດປະເພດເທື່ອ"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"​ລາຍ​ການ​ນີ້​ຖືກ​ຈັດ​ປະ​ເພດ <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ອິນ​ພຸດ​ນີ້ບໍ່​ຮອງ​ຮັບ​ການ​ສະ​ແກນ​ອັດ​ຕະ​ໂນ​ມັດ"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"ບໍ່​ສາ​ມາດ​ເລີ່ມ​ການ​ສະ​ແກນ​ອັດ​ຕະ​ໂນ​ມັດ​ສຳ​ລັບ \'<xliff:g id="TV_INPUT">%s</xliff:g>\' ໄດ້"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">ເພີ່ມ %1$d ຊ່ອງແລ້ວ</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"ບໍ່​ໄດ້​ເພີ່ມ​ຊ່ອງ"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"​ທູນ​ເນີ"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"ການ​ຄວບຄຸມ​ຂອງ​ຜູ່​ປົກ​ຄອງ"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ເປີດ"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"ປິດ"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"ປະ​ເທດ​ອື່ນໆ"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"ບໍ່ມີ"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ບໍ່ມີ"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"ບໍໄດ້ຈັດປະເພດເທື່ອ"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"ບລັອກລາຍການທີ່ຍັງບໍ່ໄດ້ຈັດປະເພດເທື່ອ"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"ບໍ່ມີ"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"ຈຳກັດສູງ"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"ຈຳກັດປານກາງ"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"ປ້ອນ​ລະ​ຫັດ​ PIN ຂອງ​ທ່ານ​ເພື່ອ​ເບິ່ງ​ຊ່ອງ​ນີ້"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"​ປ້ອນ​ລະ​ຫັດ PIN ຂອງ​ທ່ານ​ເພື່ອ​ເບິ່ງ​ລາຍ​ການ​ນີ້"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"ລາຍການນີ້ຖືກຈັດປະເພດເປັນ <xliff:g id="RATING">%1$s</xliff:g>. ກະລຸນາໃສ່ລະຫັດ PIN ຂອງທ່ານເພື່ອເບິ່ງລາຍການນີ້"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"ລາຍການນີ້ຍັງບໍ່ໄດ້ຈັດປະເພດເທື່ອ. ກະລຸນາລະບຸລະຫັດ PIN ຂອງທ່ານເພື່ອເບິ່ງລາຍການນີ້"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"​ປ້ອນ​ລະ​ຫັດ PIN ຂອງ​ທ່ານ"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"ເພື່ອ​ຕັ້ງ​ຄ່າ​ຄວບ​ຄຸມ​ຂອງ​ຜູ່​ປົກ​ຄອງ, ກະລຸ​ນາຕັ້ງ​ລະ​ຫັດ PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"ໃສ່ລະຫັດ PIN ໂຕໃຫມ່"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"ລະຫັດ PIN ນັ້ນບໍ່​ຖືກ​ຕ້ອງ, ກະ​ລຸ​ນາລອງ​ໃຫມ່​ອີກ​ຄັ້ງ."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"ລະ​ຫັດ PIN ບໍ່​ກົງ​ກັນ, ກະ​ລຸ​ນາ​ລອງ​ໃໝ່."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"ລະບຸລະຫັດ ZIP ຂອງທ່ານ."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"ແອັບ Live TV ຈະໃຊ້ລະຫັດ ZIP ເພື່ອສະໜອງຄຳແນະນຳລາຍການທີ່ສົມບູນໃຫ້ກັບຊ່ອງໂທລະທັດຕ່າງໆ."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"ໃສ່ລະຫັດ ZIP ຂອງທ່ານ"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"ລະຫັດ ZIP ບໍ່ຖືກຕ້ອງ"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"ການ​ຕັ້ງ​ຄ່າ"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"ປັບແຕ່ງ​ລາຍ​ຊື່​ຊ່ອງ"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"ເລືອກ​ຊ່ອງ​ສຳລັບການ​ແນະນຳລາຍການ​ຂອງ​ທ່ານ"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"ແຫຼ່ງທີ່ມາ​ຂອງ​ຊ່ອງ"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"ມີ​ຊ່ອງ​ໃໝ່​"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"ການ​ຄວບຄຸມ​ຂອງພໍ່ແມ່"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"ບັນທຶກໃນລະຫວ່າງເບິ່ງເພື່ອໃຫ້ທ່ານສາມາດຢຸດ ຫຼື ເບິ່ງລາຍການສົດຄືນຫຼັງໄດ້.\nຄຳເຕືອນ: ນີ້ອາດຫຼຸດອາຍຸຂອງບ່ອນຈັດເກັບຂໍ້ມູນພາຍໃນເນື່ອງຈາກມີການໃຊ້ບ່ອນຈັດເກັບຂໍ້ມູນຢ່າງຕໍ່ເນື່ອງ."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"​ໃບ​ອະ​ນຸ​ຍາດ​ Open source"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"​ໃບ​ອະ​ນຸ​ຍາດ​ແຫຼ່ງ​ເປີດ"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ສົ່ງຄຳຕິຊົມ"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"ເວີຊັນ"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"​ເພື່ອ​ເບິ່ງ​ຊ່ອງ​ນີ້, ກົດ​ປຸ່ມ ຂວາ ແລະ ປ້ອນ​ລະ​ຫັດ PIN ຂອງ​ທ່ານ"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"​ເພື່ອ​ເບິ່ງ​ລາຍ​ການ​ນີ້, ໃຫ້ກົດ​ປຸ່ມ ຂວາ ແລະ ປ້ອນ​ລະ​ຫັດ PIN ຂອງ​ທ່ານ"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"ລາຍການນີ້ບໍ່ໄດ້ຈັດປະເພດເທື່ອ.\nເພື່ອເບິ່ງລາຍການນີ້, ໃຫ້ກົດປຸ່ມຂວາແລ້ວໃສ່ລະຫັດ PIN ຂອງທ່ານ"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"​ລາຍ​ການ​ນີ້​ຖືກ​ຈັດ​ປະ​ເພດ​ <xliff:g id="RATING">%1$s</xliff:g>.\n​ເພື່ອ​ເບິ່ງ​ລາຍ​ການ​ນີ້, ໃຫ້ກົດ​ປຸ່ມ ຂວາ ແລະ ປ້ອນ​ລະ​ຫັດ PIN ຂອງ​ທ່ານ"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ເພື່ອເບິ່ງຊ່ອງນີ້, ໃຊ້ແອັບ Live TV ມາດຕະຖານ."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"ເພື່ອເບິ່ງໂປຣແກຣມນີ້, ໃຊ້ແອັບ Live TV ມາດຕະຖານ."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"ລາຍການນີ້ບໍ່ໄດ້ຈັດປະເພດເທື່ອ.\nເພື່ອເບິ່ງລາຍການນີ້, ໃຫ້ໃຊ້ແອັບ Live TV ເລີ່ມຕົ້ນ."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"ໂປຣແກຣມນີ້ຖືກຈັດປະເພດ <xliff:g id="RATING">%1$s</xliff:g>.\nເພື່ອເບິ່ງໂປຣແກຣມນີ້, ໃຊ້ແອັບ Live TV ມາດຕະຖານ."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"​ລາຍ​ການ​ຖືກບລັອກ"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"ລາຍການນີ້ບໍ່ໄດ້ຈັດປະເພດເທື່ອ"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"​ລາຍ​ການ​ນີ້​ຖືກ​ຈັດ​ປະ​ເພດ <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ສຽງເທົ່ານັ້ນ"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"ສັນຍານອ່ອນ"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"ກົດ SELECT"</b>" ເພື່ອ​ເຂົ້າ​ຫາ​ເມ​ນູ TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"ບໍ່​ພົບການ​ປ້ອນ​ເຂົ້າ TV"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"ບໍ່​ສາ​ມາດ​ຊອກ​ຫາການ​ປ້ອນ​ເຂົ້າ TV ​ໄດ້"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"ບໍ່​ຮອງ​ຮັບ PIP"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"ບໍ່ມີການຮັບສັນຍານທີ່ສາມາດສະແດງໄດ້ດ້ວຍຮູບພາບຊ້ອນຮູບພາບ PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ປະ​ເພດ​ເຄື່ອງ​ຈູນ​ບໍ່​ເໝາະ​ສົມ; ກະ​ລຸ​ນາ​ເປີດ​ໃຊ້​ແອັບ​ຊ່ອງ​ສົດ​ສຳ​ລັບ​ການ​ປ້ອນ​ເຂົ້າ TV ປະ​ເພດ​ເຄື່ອງ​ຈູນ."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ການ​ປັບ​ຊ່ອງ​ລົ້ມ​ເຫລວ"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ບໍ່ພົບແອັບຯທີ່ໃຊ້ເພື່ອດຳເນີນການ."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d ການບັນທຶກທີ່ຕັ້ງເວລາໄວ້ແລ້ວ</item>
       <item quantity="one">%1$d ການບັນທຶກທີ່ຕັ້ງເວລາໄວ້ແລ້ວ</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"ຍົກເລີກການບັນທຶກ"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"ຢຸດການບັນທຶກ"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ເບິ່ງ"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"ຫຼິ້ນຕັ້ງແຕ່ຕົ້ນ"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"ສືບຕໍ່ຫຼິ້ນວິດີໂອ"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"ເມື່ອມີໂປຣແກຣມໃຫ້ບັນທຶກຫຼາຍເກີນໄປໃນເວລາດຽວກັນ, ລະບົບຈະບັນທຶກລາຍການທີ່ມີຄວາມສຳຄັນສູງກວ່າເທົ່ານັ້ນ."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"ບັນທຶກ"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ການບັນທຶກຕາມເວລາມີຄວາມສຳຄັນສູງສຸດ"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"​ຍົກເລີກ"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"ຍົກເລີກ"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"ລືມ"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"ຢຸດ"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"ເບິ່ງຕາຕາລາງການບັນທຶກ"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"ນີ້ເປັນລາຍການດ່ຽວ"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"ບັນທຶກອັນນີ້ແທນ"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ຍົກເລີກການບັນທຶກນີ້"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"ເບິ່ງດຽວນີ້"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ລຶບການບັນທຶກອອກ…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"ບັນທຶກໄດ້"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ຕັ້ງເວລາບັນທຶກແລ້ວ"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ເກີດຄວາມຂັດແຍ່ງໃນການບັນທຶກ"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"ກຳລັງບັນທຶກ"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ບັນທຶກບໍ່ສຳເລັດ"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"ກຳລັງອ່ານເນື້ອຫາລາຍການເພື່ອຕັ້ງເວລາບັນທຶກ"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"ກຳລັງອ່ານລາຍການ"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"ກຳລັງອ່ານລາຍການ"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"ເບິ່ງການບັນທຶກຫຼ້າສຸດ"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"ບັນທຶກ <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ບໍ່ສົມບູນ."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"ບັນທຶກ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ແລະ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ບໍ່ສົມບູນ."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"ບັນທຶກ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ແລະ <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ບໍ່ສົມບູນ."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"ບັນທຶກ <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ບໍ່ສຳເລັດເນື່ອງຈາກບ່ອນຈັດເກັບຂໍ້ມູນບໍ່ພຽງພໍ."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"ບັນທຶກ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ແລະ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ບໍ່ສຳເລັດເນື່ອງຈາກບ່ອນຈັດເກັບຂໍ້ມູນບໍ່ພຽງພໍ."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"ບັນທຶກ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ແລະ <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ບໍ່ສຳເລັດເນື່ອງຈາກບ່ອນຈັດເກັບຂໍ້ມູນບໍ່ພຽງພໍ."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR ຕ້ອງໃຊ້ບ່ອນຈັດເກັບຂໍ້ມູນເພີ່ມເຕີມ"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ທ່ານຈະສາມາດບັນທຶກລາຍການດ້ວຍ DVR ໄດ້. ຢ່າງໃດກໍຕາມ, ອຸປະກອນຂອງທ່ານບໍ່ມີບ່ອນຈັດເກັບຂໍ້ມູນພຽງພໍໃຫ້ DVR ເຮັດວຽກໄດ້. ກະລຸນາເຊື່ອມຕໍ່ຫາໄດຣຟ໌ພາຍນອກທີ່ມີຂະໜາດ <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB ຫຼືໃຫຍ່ກວ່າ ແລ້ວເຮັດຕາມຂັ້ນຕອນໃນການໃຊ້ມັນເປັນອຸປະກອນຈັດເກັບຂໍ້ມູນ."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ທ່ານຈະສາມາດບັນທຶກລາຍການດ້ວຍ DVR ໄດ້. ຢ່າງໃດກໍຕາມ, ອຸປະກອນຂອງທ່ານບໍ່ມີບ່ອນຈັດເກັບຂໍ້ມູນພຽງພໍໃຫ້ DVR ເຮັດວຽກໄດ້. ກະລຸນາເຊື່ອມຕໍ່ຫາໄດຣຟ໌ພາຍນອກທີ່ມີຂະໜາດ <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB ຫຼືໃຫຍ່ກວ່າ ແລ້ວເຮັດຕາມຂັ້ນຕອນໃນການໃຊ້ມັນເປັນອຸປະກອນຈັດເກັບຂໍ້ມູນ."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"ບ່ອນຈັດເກັບຂໍ້ມູນບໍ່ພຽງພໍ"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"ຈະບໍ່ບັນທຶກລາຍການນີ້ເນື່ອງຈາກມີບ່ອນຈັດເກັບຂໍ້ມູນບໍ່ພຽງພໍ. ໃຫ້ລອງລຶບການບັນທຶກບາງອັນອອກກ່ອນ."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"ບໍ່ພົບບ່ອນຈັດເກັບຂໍ້ມູນ"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"ບໍ່ພົບບ່ອນຈັດເກັບຂໍ້ມູນບາງອັນທີ່ໃຊ້ໂດຍ DVR. ກະລຸນາເຊື່ອມຕໍ່ໄດຣຟ໌ພາຍນອກທີ່ທ່ານໃຊ້ກ່ອນຈະເປີດໃຊ້ DVR ຄືນໃໝ່. ຫຼືອີກວິທີໜຶ່ງ, ທ່ານສາມາດເລືອກໃຫ້ລືມບ່ອນຈັດເກັບຂໍ້ມູນດັ່ງກ່າວໄດ້ຫາກມັນບໍ່ມີໃຫ້ໃຊ້ອີກຕໍ່ໄປແລ້ວ."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"ລືມການຈັດເກັບຂໍ້ມູນບໍ?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"ທ່ານຈະສູນເສຍເນື້ອຫາ ແລະ ການຕັ້ງເວລາທັງໝົດທີ່ທ່ານບັນທຶກໄວ້ແລ້ວ."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"ຢຸດການບັນທຶກໄວ້ບໍ?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"ເນື້ອຫາທີ່ອັດໄວ້ແລ້ວຈະຖືກບັຍທຶກໄວ້."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"ການບັນທຶກ <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ຈະຖືກຢຸດໄວ້ເພາະມັນຂັດແຍ່ງກັບລາຍການນີ້. ເນື້ອຫາທີ່ບັນທຶກໄປແລ້ວຈະຖືກຈັດເກັບໄວ້."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ຕັ້ງເວລາການບັນທຶກແລ້ວແຕ່ມີຂໍ້ຂັດແຍ່ງເກີດຂຶ້ນ"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ເລີ່ມການບັນທຶກແລ້ວແຕ່ມີຂໍ້ຂັດແຍ່ງ"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ຈະຖືກບັນທຶກໄວ້."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"ລາຍການດຽວກັນນີ້ໄດ້ຕັ້ງເວລາໃຫ້ບັນທຶກໄວ້ແລ້ວເວລາ <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"ບັນທຶກໄປກ່ອນແລ້ວ"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"ລາຍການນີ້ຖືກບັນທຶກໄປກ່ອນແລ້ວ. ມັນສາມາດເບິ່ງໄດ້ໃນຫ້ອງສະໝຸດ DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"ຕັ້ງເວລາບັນທຶກຊີຣີແລ້ວ"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ແລ້ວ.</item>
+      <item quantity="one">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ແລ້ວ.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ແລ້ວ. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ລາຍການຈະບໍ່ຖືກບັນທຶກເນື່ອງຈາກມີຂໍ້ຂັດແຍ່ງ.</item>
+      <item quantity="one">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ແລ້ວ. ມັນຈະບໍ່ຖືກບັນທຶກເນື່ອງຈາກມີຂໍ້ຂັດແຍ່ງ.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ແລ້ວ. ຈະບໍ່ບັນທຶກເອັບພິໂສດ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ຕອນຂອງຊີຣີອື່ນເນື່ອງຈາກເວລາຂັດແຍ່ງກັນ.</item>
+      <item quantity="one">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ແລ້ວ. ຈະບໍ່ບັນທຶກເອັບພິໂສດ <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ຕອນຂອງຊີຣີອື່ນເນື່ອງຈາກເວລາຂັດແຍ່ງກັນ.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ແລ້ວ. ຈະບໍ່ບັນທຶກເອັບພິໂສດ 1 ຕອນຂອງຊີຣີອື່ນເນື່ອງຈາກເວລາຂັດແຍ່ງກັນ.</item>
+      <item quantity="one">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ແລ້ວ. ຈະບໍ່ບັນທຶກເອັບພິໂສດ 1 ຕອນຂອງຊີຣີອື່ນເນື່ອງຈາກເວລາຂັດແຍ່ງກັນ.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ແລ້ວ. ຈະບໍ່ບັນທຶກເອັບພິໂສດ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ຕອນຂອງຊີຣີອື່ນເນື່ອງຈາກເວລາຂັດແຍ່ງກັນ.</item>
+      <item quantity="one">ຕັ້ງເວລາບັນທຶກ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ລາຍການສຳລັບ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ແລ້ວ. ຈະບໍ່ບັນທຶກເອັບພິໂສດ <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ຕອນຂອງຊີຣີອື່ນເນື່ອງຈາກເວລາຂັດແຍ່ງກັນ.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"ບໍ່ພົບໂປຣແກຣມທີ່ບັນທຶໄວ້."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"ການບັນທຶກທີ່ກ່ຽວຂ້ອງ"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(ບໍ່ມີຄຳອະທິບາຍລາຍການ)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d ການບັນທຶກ</item>
       <item quantity="one">%1$d ການບັນທຶກ</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"ຢຸດການບັນທຶກຊີຣີບໍ່?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"ເອັບພິໂສດທີ່ບັນທຶກໄວ້ແລ້ວຈະຍັງຄົງສາມາດເບິ່ງໄດ້ໃນຫ້ອງສະໝຸດ DVR ຢູ່."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"ຢຸດ"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ບໍ່ມີເອັບພິໂສດໃດທີ່ກຳລັງສາຍຢູ່ໃນຕອນນີ້."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"ຍັງບໍ່ມີເອບພິໂສດທີ່ສາມາດເບິ່ງໄດ້ເທື່ອ.\nພວກມັນຈະຖືກບັນທຶອຶກເມື່ອມີການສາຍ."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d ນາທີ)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ມື້ນີ້"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ມື້ອື່ນ"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"ຄະແນນ"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"ລາຍການທີ່ບັນທຶກໄວ້ແລ້ວ"</string>
 </resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 88afdec..357b803 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"monofon."</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereof."</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Leidimo valdikliai"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Naujausi kanal."</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanalai"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV parinktys"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP parinktys"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Leidimo valdikliai negalimi šiame kanale"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Leisti arba pristabdyti"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Sukti pirmyn"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Subtitrai"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Rodymo režimas"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Įjungta"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Išjungta"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Keli garso įr."</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Gauti daug. kan."</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Nustatymai"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Šaltinis"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Sukeisti"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Įjungta"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Išjungta"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Garsas"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Pagrindinis"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP langas"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Išdėstymas"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Apač. dešinėje"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Virš. dešinėje"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Viršuje kairėje"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Apač. kairėje"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Šalia"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Dydis"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Didelis"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Mažas"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Įvesties šaltinis"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena / kabelis)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Nėra informacijos apie programą"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Informacijos nėra."</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Užblokuotas kanalas"</string>
-    <string name="default_language" msgid="4122326459624337928">"Nežinoma kalba"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Nežinoma kalba"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtitrai %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Subtitrai"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Išjungti"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Tinkinti formatavimą"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Grupuoti pagal"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Ši programa yra užblokuota"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ši programa neįvertinta"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Ši programa įvertinta kaip <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Įvestis nepalaiko automatinio nuskaitymo"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Nepavyko paleisti „<xliff:g id="TV_INPUT">%s</xliff:g>“ automatinio nuskaitymo"</string>
@@ -94,7 +76,6 @@
       <item quantity="other">Pridėta %1$d kanalų</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Nėra pridėtų kanalų"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Radijo imtuvas"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Tėvų kontrolė"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Įjungti"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Išjungti"</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Kitos šalys"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Nėra"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Nėra"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Neįvertinta"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokuoti neįvert. programas"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Nėra"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Dideli apribojimai"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Vid. apribojimai"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Įveskite PIN kodą, kad galėt. žiūrėti šį kanalą"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Įveskite PIN kodą, kad galėt. žiūrėti šią programą"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Ši programa įvertinta <xliff:g id="RATING">%1$s</xliff:g>. Įveskite PIN kodą, kad galėtumėte žiūrėti šią programą"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ši programa neįvertinta. Įveskite PIN kodą, kad galėtumėte žiūrėti šią programą"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Įveskite PIN kodą"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Jei norite nustatyti tėvų valdiklius, sukurkite PIN kodą"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Įveskite naują PIN"</string>
@@ -139,22 +123,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Tas PIN kodas buvo netinkamas. Bandykite dar kartą."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Bandykite dar kartą, PIN kodas neatitinka"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Įveskite pašto kodą."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Tiesioginių kanalų programa naudos pašto kodą, kad galėtų pateikti išsamų TV kanalų programų vadovą."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Įveskite pašto kodą"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Netinkamas pašto kodas"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Nustatymai"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Tinkinti kanalų sąrašą"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Pasirinkite programų vadovo kanalus"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanalų šaltiniai"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Galimi nauji kanalai"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Tėvų kontrolė"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Laiko poslinkis"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Įrašykite žiūrėdami, kad galėtumėte pristabdyti ar atgal atsukti tiesiogines programas.\nĮspėjimas: tai darant vidinės atminties veikimo laiką dėl intensyvaus jos naudojimo."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Atvirojo šaltinio licencijos"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Atvirojo šaltinio licencijos"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Siųsti atsiliepimą"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versija"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Jei norite žiūrėti šį kanalą, paspauskite „Tinkamas“ ir įveskite PIN kodą"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Jei norite žiūrėti šią programą, paspauskite „Tinkama“ ir įveskite PIN kodą"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ši programa neįvertinta.\nJei norite žiūrėti šią programą, paspauskite „Tinkama“ ir įveskite PIN kodą"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Ši programa įvertinta kaip <xliff:g id="RATING">%1$s</xliff:g>.\nJei norite žiūrėti šią programą, paspauskite „Tinkama“ ir įveskite PIN kodą"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Jei norite žiūrėti šį kanalą, naudokite numatytąją tiesioginės TV programą."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Jei norite žiūrėti šią programą, naudokite numatytąją tiesioginės TV programą."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ši programa neįvertinta.\nJei norite žiūrėti šią programą, naudokite numatytąją tiesioginės TV programą."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Ši programa įvertinta <xliff:g id="RATING">%1$s</xliff:g>.\nJei norite žiūrėti šią programą, naudokite numatytąją tiesioginės TV programą."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programa užblokuota"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ši programa neįvertinta"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Ši programa įvertinta kaip <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Tik garso įrašas"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Silpnas signalas"</string>
@@ -189,8 +182,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Paspauskite PASIRINKTI,"</b>" kad pasiektumėte TV meniu."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nerasta jokių TV įvesčių"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Nepavyksta rasti TV įvesties"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP nepalaikoma"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Nėra galimos įvesties, kurią galima rodyti kartu su PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Netinkamas derintuvo tipas. Paleiskite derintuvo tipo TV įvestį, skirtą programai „Live TV“."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Derinimas nepavyko"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Nerasta jokių programų šiam veiksmui apdoroti."</string>
@@ -244,6 +235,8 @@
       <item quantity="many">%1$d suplanuoto įrašo</item>
       <item quantity="other">%1$d suplanuotų įrašų</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Atšaukti įrašymą"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Sustabdyti įrašymą"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Žiūrėti"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Leisti nuo pradžios"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Tęsti ir leisti"</string>
@@ -278,9 +271,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Kai vienu metu bus per daug įrašomų programų, bus įrašomos tik aukštesnio prioriteto programos."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Išsaugoti"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Vienkartinis įrašymo veiksmas turi didžiausią prioritetą"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Atšaukti"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Atšaukti"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Pamiršti"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Sustabdyti"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Žr. įrašymo tvarkaraštį"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Ši viena programa"</string>
@@ -290,25 +280,29 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Vietoj tos įrašyti šią"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Atšaukti šį įrašymą"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Žiūrėti dabar"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Ištrinti įrašus…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Galima įrašyti"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Įrašymas suplanuotas"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Įrašo nesuderinamumas"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Įrašoma"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Įrašyti nepavyko"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Nuskaitomos programos, kad būtų sukurti įrašymo tvarkaraščiai"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Nuskaitomos programos"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Nuskaitomos programos"</string>
+    <!-- no translation found for dvr_error_insufficient_space_action_view_recent_recordings (137918938589787623) -->
     <skip />
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ įrašymo procesas nebaigtas."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"„<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>“ ir „<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>“ įrašymo procesas nebaigtas."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"„<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>“, „<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>“ ir „<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>“ įrašymo procesas nebaigtas."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ įrašymo procesas nebaigtas, nes nepakanka saugyklos vietos."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"„<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>“ ir „<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>“ įrašymo procesas nebaigtas, nes nepakanka saugyklos vietos."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"„<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>“, „<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>“ ir „<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>“ įrašymo procesas nebaigtas, nes nepakanka saugyklos vietos."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Norint naudoti DVR reikia daugiau saugyklos vietos"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Naudodami DVR galėsite įrašyti programas. Tačiau dabar įrenginyje nepakanka saugyklos vietos, kad DVR veiktų. Prijunkite išorinį diską, kuris yra <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB arba didesnis, ir atlikite veiksmus, kad formatuotumėte jį kaip įrenginio saugyklą."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Naudodami DVR galėsite įrašyti programas. Tačiau dabar įrenginyje nepakanka saugyklos vietos, kad DVR veiktų. Prijunkite išorinį diską, kuris yra <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB arba didesnis, ir atlikite veiksmus, kad formatuotumėte jį kaip įrenginio saugyklą."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Trūksta saugyklos vietos"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Ši programa nebus įrašyta, nes nepakanka saugyklos vietos. Pabandykite ištrinti kai kuriuos esamus įrašus."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Nėra saugyklos"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Nėra kai kurių saugyklų, kurias naudoja DVR. Prijunkite anksčiau naudotą išorinį diską, kad iš naujo įgalintumėte DVR. Taip pat galite pasirinkti pamiršti saugyklą, jei ji nebepasiekiama."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Pamiršti saugyklą?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Visas įrašytas turinys ir tvarkaraščiai bus prarasti."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Sustabdyti įrašymą?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Įrašytas turinys bus išsaugotas."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"„<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ įrašas bus sustabdytas dėl prieštaravimų su šia programa. Įrašytas turinys bus išsaugotas."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Įrašymas suplanuotas, bet yra neatitikimų"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Įrašymo procesas pradėtas, bet yra neatitikimų"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Programa „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>“ bus įrašyta."</string>
@@ -328,17 +322,39 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Ta pati programa jau suplanuota įrašyti <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Jau įrašyta"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Ši programa jau buvo įrašyta. Ji pasiekiama DVR bibliotekoje."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Suplanuotas serijos įrašas"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one">Suplanuotas <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašas.</item>
+      <item quantity="few">Suplanuoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašai.</item>
+      <item quantity="many">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašo.</item>
+      <item quantity="other">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašų.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one">Suplanuotas <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašas. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> iš jų nebus įraš. dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="few">Suplanuoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašai. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> iš jų nebus įraš. dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="many">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašo. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> iš jų nebus įraš. dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="other">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašų. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> iš jų nebus įraš. dėl nesuderinamo tvarkaraščio.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one">Suplanuotas <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ įrašas. Šio ir kitų serialų serijos (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) nebus įrašytos dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="few">Suplanuoti <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ įrašai. Šio ir kitų serialų serijos (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) nebus įrašytos dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="many">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ įrašo. Šio ir kitų serialų serijos (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) nebus įrašytos dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="other">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ įrašų. Šio ir kitų serialų serijos (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) nebus įrašytos dėl nesuderinamo tvarkaraščio.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one">Suplanuotas <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašas. 1 kitų serialų serija nebus įrašyta dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="few">Suplanuoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašai. 1 kitų serialų serija nebus įrašyta dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="many">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašo. 1 kitų serialų serija nebus įrašyta dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="other">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> „<xliff:g id="SERIESNAME_3">%2$s</xliff:g>“ įrašų. 1 kitų serialų serija nebus įrašyta dėl nesuderinamo tvarkaraščio.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one">Suplanuotas <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ įrašas. Kitų serialų serijos (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) nebus įrašytos dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="few">Suplanuoti <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ įrašai. Kitų serialų serijos (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) nebus įrašytos dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="many">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ įrašo. Kitų serialų serijos (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) nebus įrašytos dėl nesuderinamo tvarkaraščio.</item>
+      <item quantity="other">Suplanuota <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> „<xliff:g id="SERIESNAME_4">%2$s</xliff:g>“ įrašų. Kitų serialų serijos (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) nebus įrašytos dėl nesuderinamo tvarkaraščio.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Įrašyta programa nerasta."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Susiję įrašai"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Nėra laidos aprašo)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d įrašas</item>
       <item quantity="few">%1$d įrašai</item>
@@ -362,6 +378,8 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Sustabdyti serijos įrašymą?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Įrašytos serijos bus pasiekiamos DVR bibliotekoje."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Sustabdyti"</string>
+    <!-- no translation found for dvr_series_schedules_stopped_empty_state (1464244804664395151) -->
+    <skip />
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nėra jokių serijų.\nSerijos bus įrašytos, kai jų bus."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minutė)</item>
@@ -375,4 +393,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> šiandien"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> rytoj"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Įvertinimas"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Įrašytos programos"</string>
 </resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 00021bc..3aa06a6 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Atskaņošanas vadīklas"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Nesenie kanāli"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanāli"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV iespējas"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP opcijas"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Šim kanālam nav pieejamas atskaņošanas vadīklas."</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Atskaņot vai pauzēt"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Pārtīt uz priekšu"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Slēgtie paraksti"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Attēla režīms"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Ieslēgts"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Izslēgts"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multiaudio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Vairāk kanālu"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Iestatījumi"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Avots"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Mainīt"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Ieslēgts"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Izslēgts"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Skaņa"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Galvenais"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP logs"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Izkārtojums"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Apakšā pa labi"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Augšā pa labi"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Augšā pa kreisi"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Apakšā pa kreisi"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Līdzās"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Izmēri"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Liels"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Mazs"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Ievades avots"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/kabelis)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Nav informācijas par programmu"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Nav informācijas"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Bloķēts kanāls"</string>
-    <string name="default_language" msgid="4122326459624337928">"Nezināma valoda"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Nezināma valoda"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Slēgtie paraksti %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Slēgtie paraksti"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Izslēgti"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Pielāgot formatēšanu"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Grupēt pēc:"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Šī programma ir bloķēta."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Šī programma ir bez vērtējuma."</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Šī programma ir novērtēta kā “<xliff:g id="RATING">%1$s</xliff:g>”."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Ieeja neatbalsta automātisko meklēšanu."</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Nevar sākt automātisko skenēšanu ieejā “<xliff:g id="TV_INPUT">%s</xliff:g>”."</string>
@@ -93,7 +75,6 @@
       <item quantity="other">Tika pievienoti %1$d kanāli.</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Kanāli netika pievienoti."</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Kanālu meklētājs"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Vecāku kontrole"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Ieslēgts"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Izslēgts"</string>
@@ -109,6 +90,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Citas valstis"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Nav"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Nav"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Bez vērtējuma"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloķēt programmas bez vērtējuma"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Nav"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Stingri ierobežojumi"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Vidēji ierobežojumi"</string>
@@ -125,6 +108,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"PIN ievade, lai skatītos šo kanālu"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"PIN ievade, lai skatītos šo programmu"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Šī programma ir novērtēta kā <xliff:g id="RATING">%1$s</xliff:g>. Lai skatītos šo programmu, ievadiet PIN kodu."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Šī programma ir bez vērtējuma. Lai skatītos šo programmu, ievadiet PIN."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PIN ievade"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Lai iestatītu vecāku kontroli, izveidojiet PIN kodu."</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Ievadiet jauno PIN"</string>
@@ -137,22 +121,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN kods nav pareizs. Mēģiniet vēlreiz."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Neatbilstošs PIN. Mēģiniet vēlreiz."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Pasta indeksa ievadīšana"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Lietotnē Live Channels pasta indekss tiks izmantots, lai nodrošinātu visu TV kanālu programmu ceļvedi."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Ievadiet pasta indeksu"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Nederīgs pasta indekss"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Iestatījumi"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Pielāgot kanālu sarakstu"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Izvēlieties kanālus programmu ceļvedim."</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanālu avoti"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Pieejami jauni kanāli"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Vecāku kontrole"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Laika nobīde"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Skatīšanās laikā ierakstiet tiešraides programmas, lai varētu tās apturēt vai attīt atpakaļ.\nBrīdinājums: tas var samazināt iekšējās atmiņas lietojumu, ja atmiņa tiek intensīvi lietota."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Atklātā pirmkoda licences"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Atklātā pirmkoda licences"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Sūtīt atsauksmes"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versija"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Lai skatītos šo kanālu, nospiediet pa labi vērsto bultiņu un ievadiet PIN kodu."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Lai skatītos šo programmu, nospiediet pa labi vērsto bultiņu un ievadiet PIN kodu."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Šī programma ir bez vērtējuma.\nLai skatītos šo programmu, nospiediet pogu labajā pusē un ievadiet PIN."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Šī programma ir novērtēta kā “<xliff:g id="RATING">%1$s</xliff:g>”.\nLai skatītos šo programmu, nospiediet pa labi vērsto bultiņu un ievadiet PIN kodu."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Lai skatītos šo kanālu, izmantojiet noklusējuma lietotni televīzijas skatīšanai tiešraidē."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Lai skatītos šo programmu, izmantojiet noklusējuma lietotni televīzijas skatīšanai tiešraidē."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Šī programma ir bez vērtējuma.\nLai skatītos šo programmu, izmantojiet noklusējuma lietotni TV skatīšanai tiešraidē."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Šīs programma ir novērtēta kā “<xliff:g id="RATING">%1$s</xliff:g>”.\nLai skatītos šo programmu, izmantojiet noklusējuma programmu televīzijas skatīšanai tiešraidē."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programma ir bloķēta."</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Šī programma ir bez vērtējuma."</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Šī programma ir novērtēta kā “<xliff:g id="RATING">%1$s</xliff:g>”."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Tikai audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Vājš signāls"</string>
@@ -185,8 +178,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Nospiediet ATLASĪT"</b>", lai piekļūtu TV izvēlnei."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nav atrasta neviena TV ieeja."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Nevar atrast TV ieeju."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Funkcija PIP netiek atbalstīta."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Nav ievades, ko parādīt, izmantojot PIP."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Kanālu meklētāja veids nav piemērots. Lūdzu, palaidiet lietotni “Tiešraides kanāli” kanālu meklētāja veida TV ievadei."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Kanālu meklēšana neizdevās."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Netika atrasta neviena lietotne šīs darbības veikšanai."</string>
@@ -235,6 +226,8 @@
       <item quantity="one">%1$d ieplānots ieraksts</item>
       <item quantity="other">%1$d ieplānoti ieraksti</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Atcelt ierakstīšanu"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Apturēt ierakstīšanu"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Skatīties"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Atskaņot no sākuma"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Atsākt atskaņošanu"</string>
@@ -268,9 +261,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Ja vēlaties ierakstīt pārāk daudz programmu vienlaikus, tiks ierakstītas tikai programmas ar augstāku prioritāti."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Saglabāt"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Vienreizējiem ierakstiem ir visaugstākā prioritāte"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Atcelt"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Atcelt"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Aizmirst"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Apturēt"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Skatīt ierakstīšanas grafiku"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Šī viena programma"</string>
@@ -280,25 +270,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Tā vietā ierakstīt tālāk norādīto"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Atcelt šo ierakstīšanu"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Skatīties tūlīt"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Dzēst ierakstus…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Var ierakstīt"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Ierakstīšana ir ieplānota"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Ierakstīšanas konflikts"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Ierakstīšana"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Neizdevās ierakstīt"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Tiek lasītas programmas, lai izveidotu ierakstīšanas grafikus."</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Tiek lasītas programmas"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Tiek lasītas programmas"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Skatīt nesenos ierakstus"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"“<xliff:g id="PROGRAMNAME">%1$s</xliff:g>” ierakstīšana netika pabeigta."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"“<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>” un “<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>” ierakstīšana netika pabeigta."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"“<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>”, “<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>” un “<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>” ierakstīšana netika pabeigta."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"“<xliff:g id="PROGRAMNAME">%1$s</xliff:g>” ierakstīšana netika pabeigta, jo krātuvē nepietiek vietas."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"“<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>” un “<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>” ierakstīšana netika pabeigta, jo krātuvē nepietiek vietas."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"“<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>”, “<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>” un “<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>” ierakstīšana netika pabeigta, jo krātuvē nepietiek vietas."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Ciparvideo ierakstītājam nepieciešama lielāka krātuve"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Jūs varēsiet ierakstīt programmas, izmantojot ciparvideo ierakstītāju. Taču pašlaik jūsu ierīces krātuvē nav pietiekami daudz vietas, lai tas darbotos. Lūdzu, pievienojiet vismaz <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB lielu ārējo disku un izpildiet sniegtos norādījumus, lai formatētu to kā ierīces krātuvi."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Jūs varēsiet ierakstīt programmas, izmantojot ciparvideo ierakstītāju. Taču pašlaik jūsu ierīces krātuvē nav pietiekami daudz vietas, lai tas darbotos. Lūdzu, pievienojiet vismaz <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB lielu ārējo disku un izpildiet sniegtos norādījumus, lai formatētu to kā ierīces krātuvi."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Krātuvē nepietiek vietas"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Šī programma netiks ierakstīta, jo krātuvē nepietiek vietas. Izdzēsiet dažus esošos ierakstus."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Trūkst krātuves"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Trūkst ciparvideo ierakstītāja izmantotās krātuves. Lūdzu, pievienojiet ārējo disku, ko izmantojāt iepriekš ciparvideo ierakstītāja atkārtotai iespējošanai. Varat arī izvēlēties aizmirst krātuvi, ja tā vairs nav pieejama."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Vai aizmirst krātuvi?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Viss jūsu ierakstītais saturs un grafiki tiks zaudēti."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Vai apturēt ierakstīšanu?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Ierakstītais saturs tiks saglabāts."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Seriāla “<xliff:g id="PROGRAMNAME">%1$s</xliff:g>” ierakstīšana tiks apturēta, jo ir konflikts ar šo programmu. Ierakstītais saturs tiks saglabāts."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Ierakstīšana ir ieplānota, taču ir konflikti"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Ierakstīšana tika sākta, taču ir konflikti"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Programma <xliff:g id="PROGRAMNAME">%1$s</xliff:g> tiks ierakstīta."</string>
@@ -314,17 +307,34 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Šo pārraidi jau ir plānots ierakstīt plkst. <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Jau tika ierakstīta"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Šī pārraide jau ir ierakstīta. Tā ir pieejama DVR bibliotēkā."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Ir ieplānota seriāla ierakstīšana"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="zero">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksti.</item>
+      <item quantity="one">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānots <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksts.</item>
+      <item quantity="other">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksti.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="zero">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksti. Konfliktu dēļ netiks ierakstīts(-i) <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> no tiem.</item>
+      <item quantity="one">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānots <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksts. Konfliktu dēļ netiks ierakstīts(-i) <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> no tiem.</item>
+      <item quantity="other">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksti. Konfliktu dēļ netiks ierakstīts(-i) <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> no tiem.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="zero">Seriālam <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ieraksti. Konfliktu dēļ netiks ierakstītas <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> šī un cita(-u) seriāla(-u) sērijas.</item>
+      <item quantity="one">Seriālam <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ir ieplānots <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ieraksts. Konfliktu dēļ netiks ierakstītas <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> šī un cita(-u) seriāla(-u) sērijas.</item>
+      <item quantity="other">Seriālam <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ieraksti. Konfliktu dēļ netiks ierakstītas <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> šī un cita(-u) seriāla(-u) sērijas.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="zero">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksti. Konfliktu dēļ netiks ierakstīta 1 cita seriāla sērija.</item>
+      <item quantity="one">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānots <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksts. Konfliktu dēļ netiks ierakstīta 1 cita seriāla sērija.</item>
+      <item quantity="other">Seriālam <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ieraksti. Konfliktu dēļ netiks ierakstīta 1 cita seriāla sērija.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="zero">Seriālam <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ieraksti. Konfliktu dēļ netiks ierakstītas <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> cita seriāla sērijas.</item>
+      <item quantity="one">Seriālam <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ir ieplānots <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ieraksts. Konfliktu dēļ netiks ierakstītas <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> cita seriāla sērijas.</item>
+      <item quantity="other">Seriālam <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ir ieplānoti <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ieraksti. Konfliktu dēļ netiks ierakstītas <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> cita seriāla sērijas.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Ierakstītā programma netika atrasta."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Saistītie ieraksti"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Nav programmas apraksta)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="zero">%1$d ierakstu</item>
       <item quantity="one">%1$d ieraksts</item>
@@ -346,6 +356,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Vai apturēt sērijas ierakstīšanu?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Ierakstītās sērijas būs pieejamas DVR bibliotēkā."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Apturēt"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Šobrīd nav iznākusi neviena sērija."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nav pieejama neviena sērija.\nTās tiks ierakstītas, kad būs pieejamas."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="zero">(%1$d minūtes)</item>
@@ -358,4 +369,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Plkst. <xliff:g id="TIME_RANGE">%1$s</xliff:g> šodien"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Plkst. <xliff:g id="TIME_RANGE">%1$s</xliff:g> rīt"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Rezultāts"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Ierakstītās programmas"</string>
 </resources>
diff --git a/res/values-mk-v23/strings.xml b/res/values-mk-rMK-v23/strings.xml
similarity index 100%
rename from res/values-mk-v23/strings.xml
rename to res/values-mk-rMK-v23/strings.xml
diff --git a/res/values-mk/arrays.xml b/res/values-mk-rMK/arrays.xml
similarity index 100%
rename from res/values-mk/arrays.xml
rename to res/values-mk-rMK/arrays.xml
diff --git a/res/values-mk/rating_system_strings.xml b/res/values-mk-rMK/rating_system_strings.xml
similarity index 100%
rename from res/values-mk/rating_system_strings.xml
rename to res/values-mk-rMK/rating_system_strings.xml
diff --git a/res/values-mk/strings.xml b/res/values-mk-rMK/strings.xml
similarity index 78%
rename from res/values-mk/strings.xml
rename to res/values-mk-rMK/strings.xml
index 566377a..4de54ac 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"моно"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"стерео"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Контроли за игри"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Последни канали"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Канали"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"ТВ опции"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Опции за ПИП"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Контролите за репродуцирање се недостапни за овој канал"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Пуштање или паузирање"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Брзо премотување напред"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Затворени титли"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Реж. на прикаж."</string>
     <string name="options_item_pip" msgid="3951350386626879645">"ПИП"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Вклучено"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Исклучено"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Мултиаудио"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Добиј уште канали"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Поставки"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Извор"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Замени"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Вклучено"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Исклучено"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Звук"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Главен"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"ПИП прозорец"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Распоред"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Долу десно"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Горе десно"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Горе лево"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Долу лево"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Едно до друго"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Големина"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Голема"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Мала"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Влезен извор"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ТВ (антена/кабел)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Нема информации за програмата"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Нема информации"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Блокиран канал"</string>
-    <string name="default_language" msgid="4122326459624337928">"Непознат јазик"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Непознат јазик"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Затворени титлови %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Затворени титли"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Исклучено"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Прилаг. форматирање"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Групирај по"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Оваа програма е блокиранa"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Програмава е неоценета"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Оваа програма е оценета <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Влезот не поддржува автоматско скенирање"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Не може да се вклучи автоскенирање на „<xliff:g id="TV_INPUT">%s</xliff:g>“"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d канали се додадени</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Не се додадени канали"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Приемник"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Родител. контрола"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Вклучено"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Исклучено"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Останати земји"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ништо"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ништо"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Неоценето"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Блокирај неоценети програми"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ништо"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Големи ограничување"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Средно ограничување"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Внесете го вашиот PIN за да го гледате каналот"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Внесете го вашиот PIN за да ја гледате програмата"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Програмава е оценета со <xliff:g id="RATING">%1$s</xliff:g>. Внесете го PIN-кодот за да ја гледате"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Програмава е неоценета. Внесете го PIN-кодот за да ја гледате"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Внесете го вашиот PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"За да поставите родителска контрола, креирајте PIN."</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Внесете го новиот PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN-кодот е погрешен. Обидете се повторно."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Обидете се повторно, PIN-кодот не се совпаѓа"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Внесете го поштенскиот број."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Апликацијата Live TV ќе го користи поштенскиот број за да обезбеди целосен програмски водич за ТВ-каналите."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Внесете го поштенскиот број"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Неважечки поштенски број"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Поставки"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Приспособи го списокот канали"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Изберете канали за програмскиот водич"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Извори на канали"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Достапни се нови канали"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Родителски надзор"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Снимање"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Снимајте додека гледате за да може да ги паузирате или да ги премотувате наназад програмите во живо.\nПредупредување: ова може да го намали траењето на внатрешната меморија поради нејзиното интензивно искористување."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Лиценци за софтвер со отворен код"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Лиценци за отворен код"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Испратете повратни информации"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Верзија"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"За да го гледате овој канал, притиснете Во ред и внесете го вашиот PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"За да ја гледате оваа програма, притиснете Во ред и внесете го вашиот PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Програмава е неоценета.\nЗа да ја гледате, притиснете Во ред и внесете го PIN-кодот"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Оваа програма е оценета <xliff:g id="RATING">%1$s</xliff:g>.\nЗа да ја гледате оваа програма, притиснете Во ред и внесете го PIN-от."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"За да го гледате овој канал, користете ја стандардната апликација за телевизија во живо."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"За да ја гледате програмава, користете ја стандардната апликација за телевизија во живо."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Програмава е неоценета.\nЗа да ја гледате, користете ја стандардната апликација за телевизија во живо."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Оваа програма е оценета <xliff:g id="RATING">%1$s</xliff:g>.\nЗа да ја гледате програмава, користете ја стандардната апликација за телевизија во живо."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Програмата е блокирана"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Програмава е неоценета"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Оваа програма е оценета <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Само звук"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Слаб сигнал"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Притиснете ИЗБЕРИ"</b>" за да пристапите до ТВ-менито."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Не е пронајден ТВ-влез"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"ТВ-влезот не може да се најде"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"ПИП не е поддржано"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Нема достапен влез што може да се прикаже со ПИП"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Типот приемник не е соодветен. Стартувајте ја апликацијата Live TV за ТВ-влез од типот приемник."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Бирањето не успеа"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Не е пронајдена апликација што ќе се справи со ова дејство."</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d закажано снимање</item>
       <item quantity="other">%1$d закажани снимања</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Откажи го снимањето"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Сопри со снимање"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Часовник"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Репродуцирај отпочеток"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Прод. репродукција"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Кога има повеќе програми што треба да се снимаат во исто време, ќе се снимат само оние со повисок приоритет."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Зачувај"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Еднократните снимања имаат највисок приоритет"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Откажи"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Откажи"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Заборави"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Сопри"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Прикажи распоред на снимање"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Само оваа програма"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Наместо неа, снимај ја оваа"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Откажете го снимањево"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Гледајте сега"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Избришете ги снимките…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Може да се снима"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Снимањето е закажано"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Конфликт при снимање"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Се снима"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Неуспешно снимање"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Се читаат програми за да се создадат распореди за снимање"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Се читаат програми"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Се читаат програми"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Прегледајте ги последните снимки"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Снимањето на <xliff:g id="PROGRAMNAME">%1$s</xliff:g> е незавршено."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Снимањата на <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> и <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> се незавршени."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Снимањата на <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> и <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> се незавршени."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Снимањето на <xliff:g id="PROGRAMNAME">%1$s</xliff:g> не заврши поради недоволен простор за складирање."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Снимањата <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> и <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> не завршија поради недоволен простор за складирање."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Снимањата <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> и <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> не завршија поради недоволен простор за складирање."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Потребна е поголема меморија за DVR"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Ќе може да снимате програми со DVR. Но во моментов нема доволно простор на вашиот уред за да може DVR да функционира. Поврзете надворешна податочна едница од <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB или повеќе и следете ги чекорите за да ја форматирате како меморија на уредот."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Ќе може да снимате програми со DVR. Но во моментов нема доволно простор на вашиот уред за да може DVR да функционира. Поврзете надворешна податочна едница од <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB или повеќе и следете ги чекорите за да ја форматирате како меморија на уредот."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Нема доволно меморија"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Програмава нема да се сними бидејќи нема доволно меморија. Обидете се да избришете постоечки снимки."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Недостасува простор"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Недостасува дел од просторот што го користи DVR. Поврзете го надворешниот диск што го користевте претходно за да овозможите DVR повторно. Во спротивно, може да изберете да се заборави просторот ако веќе не е достапен."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Да се заборави просторот?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Сите ваши снимени содржини и распореди ќе се изгубат."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Да се сопре со снимање?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Снимените содржини ќе се зачуваат."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Снимањето на <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ќе прекине поради конфликти со програмава. Снимената содржина ќе се зачува."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Снимањето е закажано, но постојат конфликти"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Снимањето започна, но постојат конфликти"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ќе се сними."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Истата програма е веќе закажана за снимање во <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Веќе е снимена"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Програмава е веќе снимена. Достапна е во DVR-збирката."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Закажано е снимање серија"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимање е закажано за <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања се закажани за <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимање е закажано за <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> од нив нема да се снимат поради конфликти.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања се закажани за <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> од нив нема да се снимат поради конфликти.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимање е закажано за <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизоди од оваа и други серии нема да се снимат поради конфликти.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимања се закажани за <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизоди од оваа и други серии нема да се снимат поради конфликти.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимање е закажано за <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 епизода од други серии нема да се сними поради конфликти.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања се закажани за <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 епизода од други серии нема да се сними поради конфликти.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимање е закажано за <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизоди од други серии нема да се снимат поради конфликти.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимања се закажани за <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизоди од други серии нема да се снимат поради конфликти.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Снимената програма не е пронајдена."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Поврзани снимки"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Нема опис на програмата)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d снимка</item>
       <item quantity="other">%1$d снимки</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Да се сопре снимањето на серијата?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Снимените епизоди ќе останат достапни во DVR-збирката."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Сопри"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Не се емитуваат епизоди во моментов."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Не се достапни епизоди.\nЌе се снимат штом ќе бидат достапни."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d минута)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> денес"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> утре"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Оценка"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Снимени програми"</string>
 </resources>
diff --git a/res/values-ml-v23/strings.xml b/res/values-ml-rIN-v23/strings.xml
similarity index 100%
rename from res/values-ml-v23/strings.xml
rename to res/values-ml-rIN-v23/strings.xml
diff --git a/res/values-ml/arrays.xml b/res/values-ml-rIN/arrays.xml
similarity index 100%
rename from res/values-ml/arrays.xml
rename to res/values-ml-rIN/arrays.xml
diff --git a/res/values-ml/rating_system_strings.xml b/res/values-ml-rIN/rating_system_strings.xml
similarity index 100%
rename from res/values-ml/rating_system_strings.xml
rename to res/values-ml-rIN/rating_system_strings.xml
diff --git a/res/values-ml/strings.xml b/res/values-ml-rIN/strings.xml
similarity index 76%
rename from res/values-ml/strings.xml
rename to res/values-ml-rIN/strings.xml
index e29a875..77e4623 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"മോണോ"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"സ്‌റ്റീരിയോ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"പ്ലേ നിയന്ത്രണങ്ങൾ"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"ഏറ്റവും പുതിയ ചാനലുകൾ"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ചാനലുകൾ"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"ടിവി ഓപ്‌ഷനുകൾ"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP ഓ‌പ്‌ഷനുകൾ"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ഈ ചാനലിന് പ്ലേ നിയന്ത്രണങ്ങൾ ലഭ്യമല്ല"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"പ്ലേ ചെയ്യുക അല്ലെങ്കിൽ താല്‍‌ക്കാലികമായി നിര്‍‌ത്തുക"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"വേഗത്തിലുള്ള കൈമാറൽ"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"അടച്ച അടിക്കുറിപ്പുകൾ"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"ഡിസ്‌പ്ലേ മോഡ്"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"ഓണാണ്"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"ഓഫാണ്"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"മൾട്ടി ഓഡിയോ"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"കൂടുതൽ ചാനൽ സ്വീകരിക്കൂ"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"ക്രമീകരണം"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"ഉറവിടം"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"സ്വാപ്പുചെയ്യുക"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"ഓണാണ്"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"ഓഫാണ്"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ശബ്ദം"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"പ്രധാന വിൻഡോ"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP വിൻഡോ"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"ലേ‌ഔട്ട്"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"ചുവടെ വലതുഭാഗത്ത്"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"മുകളില്‍‌ വലതുഭാഗത്ത്"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"മുകളില്‍‌ ഇടതുഭാഗത്ത്"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"ചുവടെ ഇടതുഭാഗത്ത്"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"വശങ്ങളിലായി"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"വലുപ്പം"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"വലുത്"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"ചെറുത്"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"ഇൻപുട്ട് ഉറവിടം"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ടിവി (ആന്റിന/കേബിൾ)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"പ്രോഗ്രാം വിവരമൊന്നുമില്ല"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"വിവരമൊന്നുമില്ല"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"തടഞ്ഞ ചാനൽ"</string>
-    <string name="default_language" msgid="4122326459624337928">"അറിയാത്ത ഭാഷ"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"അറിയാത്ത ഭാഷ"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"അടച്ച അടിക്കുറിപ്പുകൾ %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"അടച്ച അടിക്കുറിപ്പുകൾ"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"ഓഫ്"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ഫോർമാറ്റുചെയ്യൽ ഇഷ്‌ടാനുസൃതമാക്കുക"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"ഗ്രൂപ്പ് അനുസരിച്ച്"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"ഈ പ്രോഗ്രാം തടഞ്ഞിരിക്കുന്നു"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"ഈ പ്രോഗ്രാം റേറ്റുചെയ്‌തിട്ടില്ല"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"ഈ പ്രോഗ്രാമിനെ <xliff:g id="RATING">%1$s</xliff:g> എന്ന് റേറ്റുചെയ്‌തു"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"സ്വയമേവ സ്‌കാൻ ചെയ്യുന്നതിനെ ഇൻപുട്ട് പിന്തുണയ്‌ക്കുന്നില്ല"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' എന്നതിനായി യാന്ത്രിക സ്‌കാൻ ആരംഭിക്കാനായില്ല"</string>
@@ -90,7 +72,6 @@
     <!-- String.format failed for translation -->
     <!-- no translation found for msg_channel_added (5301526166755938705) -->
     <string name="msg_no_channel_added" msgid="2882586037409921925">"ചാനലുകളൊന്നും ചേർത്തിട്ടില്ല"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ട്യൂണർ"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"രക്ഷാകർതൃ നിയന്ത്രണങ്ങൾ"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ഓൺ"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"ഓഫ്"</string>
@@ -106,6 +87,8 @@
     <string name="other_countries" msgid="8342216398676184749">"മറ്റു രാജ്യങ്ങൾ"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"ഒന്നുമില്ല"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ഒന്നുമില്ല"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"റേറ്റുചെയ്‌തിട്ടില്ല"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"റേറ്റുചെയ്യാത്ത പ്രോഗ്രാം ബ്ലോക്കുചെയ്യുക"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"ഒന്നുമില്ല"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"ഉയർന്ന നിയന്ത്രണങ്ങൾ"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"ഇടത്തരം നിയന്ത്രണങ്ങൾ"</string>
@@ -122,6 +105,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"ഈ ചാനൽ കാണാൻ നിങ്ങളുടെ പിൻ നൽകുക"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"ഈ പ്രോഗ്രാം കാണാൻ നിങ്ങളുടെ പിൻ നൽകുക"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"ഈ പ്രോഗ്രാമിനെ <xliff:g id="RATING">%1$s</xliff:g> എന്ന് റേറ്റുചെയ്‌തു. ഈ പ്രോഗ്രാം കാണുന്നതിന് നിങ്ങളുടെ പിൻ നൽകുക."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"ഈ പ്രോഗ്രാം റേറ്റുചെയ്‌തിട്ടില്ല. ഇത് കാണാൻ നിങ്ങളുടെ പിൻ നൽകുക"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"നിങ്ങളുടെ പിൻ നൽകുക"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"രക്ഷാകർതൃ നിയന്ത്രണങ്ങൾ സജ്ജമാക്കാൻ, ഒരു പിൻ സൃഷ്‌ടിക്കുക"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"പുതിയ പിൻ നൽകുക"</string>
@@ -133,22 +117,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"നൽകിയ പിൻ തെറ്റാണ്. വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"പിൻ യോജിക്കുന്നില്ല, വീണ്ടും ശ്രമിക്കുക"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"നിങ്ങളുടെ തപാൽ കോഡ് നൽകുക."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"ടിവി ചാനലുകൾക്ക് സമ്പൂർണ്ണ പ്രോഗ്രാം ഗൈഡ് നൽകുന്നതിന് തത്സമയ ചാനലുകൾ ആപ്പ്, തപാൽ കോഡ് ഉപയോഗിക്കും."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"നിങ്ങളുടെ തപാൽ കോഡ് നൽകുക"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"തെറ്റായ തപാൽ കോഡ്"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"ക്രമീകരണം"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"ചാനൽ ലിസ്റ്റ് ഇഷ്‌ടാനുസൃതമാക്കൂ"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"നിങ്ങളുടെ പ്രോഗ്രാം ഗൈഡിനായി ചാനലുകൾ തിരഞ്ഞെടുക്കുക"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"ചാനൽ ഉറവിടങ്ങൾ"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"പുതിയ ചാനലുകൾ ലഭ്യമാണ്"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"രക്ഷാകർതൃ നിയന്ത്രണങ്ങൾ"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"ടൈംഷിഫ്റ്റ്"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"കാണുന്നതിനിടയിൽ റെക്കോർഡുചെയ്യുക, അതുവഴി നിങ്ങൾക്ക് തത്സമയ പ്രോഗ്രാമുകൾ തൽക്കാലം നിർത്താനോ റീവൈൻഡുചെയ്യാനോ കഴിയും.\nമുന്നറിയിപ്പ്: ഇങ്ങനെ ചെയ്യുമ്പോൾ, ഇന്റേണൽ സ്റ്റോറേജ് അധികമായി ഉപയോഗിക്കപ്പെടുന്നതിനാൽ സ്റ്റോറേജിന്റെ ലൈഫ് കുറഞ്ഞേക്കാം."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"ഓപ്പൺ സോഴ്‌സ് ലൈസൻസ്"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"ഓപ്പൺ സോഴ്‌സ് ലൈസൻസുകൾ"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ഫീഡ്‍ബാക്ക് അയയ്ക്കുക"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"പതിപ്പ്"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"ഈ ചാനൽ കാണുന്നതിന് വലതുവശത്ത് അമർത്തിക്കൊണ്ട് നിങ്ങളുടെ പിൻ നൽകുക"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"ഈ പ്രോഗ്രാം കാണുന്നതിന് വലതുവശത്ത് അമർത്തിക്കൊണ്ട് നിങ്ങളുടെ പിൻ നൽകുക"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"ഈ പ്രോഗ്രാം റേറ്റുചെയ്‌തിട്ടില്ല.\nഇത് കാണാൻ, വലതുവശത്ത് അമർത്തിയശേഷം നിങ്ങളുടെ പിൻ നൽകുക"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"ഈ പ്രോഗ്രാമിനെ <xliff:g id="RATING">%1$s</xliff:g> എന്ന് റേറ്റുചെയ്‌തു.\nഈ പ്രോഗ്രാം കാണുന്നതിന് വലതുവശത്ത് അമർത്തിക്കൊണ്ട് നിങ്ങളുടെ പിൻ നൽകുക."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ഈ ചാനൽ കാണുന്നതിന്, സ്ഥിര \'തത്സമയ ടിവി ആപ്പ്\' ഉപയോഗിക്കുക."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"ഈ പ്രോഗ്രാം കാണുന്നതിന്, സ്ഥിര \'തത്സമയ ടിവി ആപ്പ്\' ഉപയോഗിക്കുക."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"ഈ പ്രോഗ്രാം റേറ്റുചെയ്‌തിട്ടില്ല.\nഇത് കാണാൻ ഡിഫോൾട്ട് തത്സമയ ടിവി ആപ്പ് ഉപയോഗിക്കുക."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"ഈ പ്രോഗ്രാമിനെ <xliff:g id="RATING">%1$s</xliff:g> എന്ന് റേറ്റുചെയ്‌തു.\nഈ പ്രോഗ്രാം കാണുന്നതിന് സ്ഥിര \'തത്സമയ ടിവി ആപ്പ്\' ഉപയോഗിക്കുക."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"പ്രോഗ്രാം തടഞ്ഞു"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"ഈ പ്രോഗ്രാം റേറ്റുചെയ്‌തിട്ടില്ല"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"ഈ പ്രോഗ്രാമിനെ <xliff:g id="RATING">%1$s</xliff:g> എന്ന് റേറ്റുചെയ്‌തു"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ഓഡിയോ മാത്രം"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"സിഗ്‌നൽ ദുർബലമാണ്"</string>
@@ -179,8 +172,6 @@
     <string name="intro_description" msgid="7806473686446937307">"ടിവി മെനു ആക്‌സസ്സ് ചെയ്യാൻ "<b>"\'തിരഞ്ഞെടുക്കുക\' അമർത്തുക"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"ടിവി ഇൻപുട്ടൊന്നും കണ്ടെത്തിയില്ല"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"ടിവി ഇൻപുട്ട് കണ്ടെത്താനാകില്ല"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP പിന്തുണയ്‌ക്കുന്നില്ല"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP-യിൽ കാണിക്കാനാകുന്ന ഇൻപുട്ടൊന്നും ലഭ്യമല്ല"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ട്യൂണർ തരം അനുയോജ്യമല്ല. ട്യൂണർ തരം ടിവി ഇൻപുട്ടിനായി തത്സമയ ചാനലുകളുടെ അപ്ലിക്കേഷൻ സമാരംഭിക്കുക."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ട്യൂൺ ചെയ്യൽ പരാജയപ്പെട്ടു"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ഈ പ്രവർത്തനം കൈകാര്യം ചെയ്യാൻ ആപ്പുകളൊന്നും കണ്ടെത്തിയില്ല."</string>
@@ -224,6 +215,8 @@
       <item quantity="other">%1$d റെക്കോർഡിംഗുകൾ ഷെഡ്യൂൾ ചെയ്തു</item>
       <item quantity="one">%1$d റെക്കോർഡിംഗ് ഷെഡ്യൂൾ ചെയ്തു</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"റെക്കോർഡിംഗ് റദ്ദാക്കുക"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"റെക്കോർഡിംഗ് നിർത്തുക"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"കാ‍ണുക"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"തുടക്കം മുതൽ പ്ലേ ചെയ്യുക"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"പ്ലേ പുനരാരംഭിക്കുക"</string>
@@ -256,9 +249,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"ഒരേ സമയം നിരവധി പരിപാടികൾ റെക്കോർഡുചെയ്യേണ്ടതുണ്ടെങ്കിൽ, ഉയർന്ന മുൻഗണനകളുള്ള പ്രോഗ്രാമുകൾ മാത്രം റെക്കോർഡുചെയ്യപ്പെടും."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"സംരക്ഷിക്കുക"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ഒറ്റത്തവണ റെക്കോർഡിംഗുകൾക്ക് ഏറ്റവും ഉയർന്ന മുൻഗണന"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"റദ്ദാക്കൂ"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"റദ്ദാക്കുക"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"മറക്കുക"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"നിർത്തുക"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"റെക്കോർഡിംഗ് ഷെഡ്യൂൾ കാണുക"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"ഈ ഒരൊറ്റ പ്രോഗ്രാം"</string>
@@ -268,25 +258,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"പകരം, ഇത് റെക്കോർഡ് ചെയ്യുക"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ഈ റെക്കോർഡിംഗ് റദ്ദാക്കുക"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"ഇപ്പോൾ കാണുക"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"റെക്കോർഡിംഗുകൾ ഇല്ലാതാക്കുക…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"റെക്കോർഡുചെയ്യാവുന്നത്"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"റെക്കോർഡിംഗ് ഷെഡ്യൂൾചെയ്‌തു"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"റെക്കോർഡിംഗ് പൊരുത്തക്കേട്"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"റെക്കോർഡിംഗ്"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"റെക്കോർഡുചെയ്യൽ പരാജയപ്പെട്ടു"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"റെക്കോർഡിംഗ് ഷെഡ്യൂളുകൾ സൃഷ്ടിക്കാൻ പ്രോഗ്രാമുകൾ വായിക്കുന്നു"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"വായനാ പ്രോഗ്രാമുകൾ"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"വായനാ പ്രോഗ്രാമുകൾ"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"സമീപകാല റെക്കോർഡിംഗുകൾ കാണുക"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> റെക്കോർഡുചെയ്യൽ പൂർണ്ണമായില്ല."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> എന്നിവയുടെ റെക്കോർഡുചെയ്യൽ പൂർണ്ണമായില്ല."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> എന്നിവയുടെ റെക്കോർഡുചെയ്യൽ പൂർണ്ണമായില്ല."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"വേണ്ടത്ര സ്റ്റോറേജ് ഇല്ലാത്തതിനാൽ <xliff:g id="PROGRAMNAME">%1$s</xliff:g> റെക്കോർഡുചെയ്യൽ പൂർത്തിയായില്ല."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"വേണ്ടത്ര സ്റ്റോറേജ് ഇല്ലാത്തതിനാൽ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> എന്നിവയുടെ റെക്കോർഡുചെയ്യൽ പൂർത്തിയായില്ല."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"വേണ്ടത്ര സ്റ്റോറേജ് ഇല്ലാത്തതിനാൽ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> എന്നിവയുടെ റെക്കോർഡുചെയ്യൽ പൂർത്തിയായില്ല."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR-ന് കൂടുതൽ സ്റ്റോറേജ് ആവശ്യമാണ്"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR ഉപയോഗിച്ച് നിങ്ങൾക്ക് പ്രോഗ്രാമുകൾ റെക്കോർഡുചെയ്യാനാകും. എന്നിരുന്നാലും, DVR പ്രവർത്തിക്കുന്നതിന് നിങ്ങളുടെ ഉപകരണത്തിൽ ഇപ്പോൾ വേണ്ടത്ര സ്റ്റോറേജ് ഇല്ല. <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB-യോ കൂടുതലോ ഉള്ള ഒരു എക്സ്റ്റേണൽ ഡ്രൈവ് കണക്റ്റുചെയ്യുകയും ഉപകരണ സ്റ്റോറേജായി അത് ഫോർമാറ്റുചെയ്യുന്നതിന് നിർദ്ദേശങ്ങൾ പിന്തുടരുകയും ചെയ്യുക."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"DVR ഉപയോഗിച്ച് നിങ്ങൾക്ക് പ്രോഗ്രാമുകൾ റെക്കോർഡുചെയ്യാനാകും. എന്നിരുന്നാലും, DVR പ്രവർത്തിക്കുന്നതിന് നിങ്ങളുടെ ഉപകരണത്തിൽ ഇപ്പോൾ വേണ്ടത്ര സ്റ്റോറേജ് ഇല്ല. <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB-യോ കൂടുതലോ ഉള്ള ഒരു എക്സ്റ്റേണൽ ഡ്രൈവ് കണക്റ്റുചെയ്യുകയും ഉപകരണ സ്റ്റോറേജായി അത് ഫോർമാറ്റുചെയ്യുന്നതിന് നിർദ്ദേശങ്ങൾ പിന്തുടരുകയും ചെയ്യുക."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"മതിയായ സ്റ്റോറേജ് ഇല്ല"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"മതിയായ സ്റ്റോറേജ് ഇല്ലാത്തതിനാൽ ഈ പ്രോഗ്രാം റെക്കോർഡ് ചെയ്യപ്പെടില്ല. നിലവിലുള്ള റെക്കോർഡിംഗുകളിൽ ചിലത് ഇല്ലാതാക്കിക്കൊണ്ട് ശ്രമിച്ചുനോക്കുക."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"നഷ്ടമായ സ്റ്റോറേജ്"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR ഉപയോഗിക്കുന്ന സ്റ്റോറേജിന്റെ ചിലത് നഷ്ടമായിരിക്കുന്നു. വീണ്ടും DVR പ്രവർത്തനക്ഷമമാക്കുന്നതിന്, നിങ്ങൾ മുമ്പ് ഉപയോഗിച്ച എക്സ്റ്റേണൽ ഡ്രൈവ് കണക്റ്റുചെയ്യുക. സ്റ്റോറേജ് തുടർന്നങ്ങോട്ട് ലഭ്യമല്ലെങ്കിൽ, ഇതരമാർഗ്ഗമെന്ന നിലയിൽ, നിങ്ങൾക്ക് മറക്കുന്നതിന് തിരഞ്ഞെടുക്കാവുന്നതാണ്."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"സ്റ്റോറേജ് മറക്കണോ?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"നിങ്ങളുടെ റെക്കോർഡ് ചെയ്തിട്ടുള്ള എല്ലാ ഉള്ളടക്കവും ഷെഡ്യൂളുകളും നഷ്ടപ്പെടും."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"റെക്കോർഡിംഗ് നിർത്തണോ?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"റെക്കോർഡുചെയ്തിട്ടുള്ള ഉള്ളടക്കം സംരക്ഷിക്കപ്പെടും."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"ഈ പ്രോഗ്രാമുമായി പൊരുത്തക്കേട് ഉള്ളതിനാൽ  <xliff:g id="PROGRAMNAME">%1$s</xliff:g> എന്ന പ്രോഗ്രാമിന്റെ റെക്കോർഡിംഗ് അവസാനിപ്പിക്കും. റെക്കോർഡുചെയ്ത ഉള്ളടക്കം സംരക്ഷിക്കപ്പെടും."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"റെക്കോർഡിംഗ് ഷെഡ്യൂൾ ചെയ്തിരിക്കുന്നു, എന്നാൽ പൊരുത്തക്കേടുകൾ ഉണ്ട്"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"റെക്കോർഡിംഗ് ആരംഭിച്ചിരിക്കുന്നു, എന്നാൽ പൊരുത്തക്കേടുകൾ ഉണ്ട്"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> റെക്കോർഡുചെയ്യപ്പെടും."</string>
@@ -304,17 +297,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"ഇതേ പ്രോഗ്രാം <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>-ന് റെക്കോർഡ് ചെയ്യുന്നതിനായി ഇതിനകം തന്നെ ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"ഇതിനകം തന്നെ റെക്കോർഡ് ചെയ്തു"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"ഈ പ്രോഗ്രാം ഇതിനകം തന്നെ റെക്കോർഡ് ചെയ്തിട്ടുണ്ട്. DVR ലൈഒബ്രറിയിൽ ഇത് ലഭ്യമാണ്."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"പരമ്പരയുടെ റെക്കോർഡിംഗ് ഷെഡ്യൂൾ ചെയ്‌തു"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> റെക്കോർഡിംഗുകൾ ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> റെക്കോർഡിംഗ് ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> റെക്കോർഡിംഗുകൾ ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്. പൊരുത്തക്കേടുകൾ ഉള്ളതിനാൽ അവയിലെ <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> എണ്ണം റെക്കോർഡുചെയ്യപ്പെടില്ല.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> റെക്കോർഡിംഗ് ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്. പൊരുത്തക്കേടുകൾ ഉള്ളതിനാൽ അത് റെക്കോർഡ് ചെയ്യപ്പെടില്ല.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> റെക്കോർഡിംഗുകൾ ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്. പൊരുത്തക്കേടുകൾ ഉള്ളതിനാൽ ഈ പരമ്പരയുടെയും മറ്റ് പരമ്പരയുടെയും <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> എപ്പിസോഡുകൾ റെക്കോർഡുചെയ്യപ്പെടില്ല.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> റെക്കോർഡിംഗ് ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്. പൊരുത്തക്കേടുകൾ ഉള്ളതിനാൽ ഈ പരമ്പരയുടെയും മറ്റ് പരമ്പരയുടെയും <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> എപ്പിസോഡുകൾ റെക്കോർഡുചെയ്യപ്പെടില്ല.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> റെക്കോർഡിംഗുകൾ ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്. പൊരുത്തക്കേടുകൾ ഉള്ളതിനാൽ മറ്റ് പരമ്പരയുടെ ഒരു എപ്പിസോഡ് റെക്കോർഡുചെയ്യപ്പെടില്ല.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> റെക്കോർഡിംഗ് ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്. പൊരുത്തക്കേടുകൾ ഉള്ളതിനാൽ മറ്റ് പരമ്പരയുടെ ഒരു എപ്പിസോഡ് റെക്കോർഡുചെയ്യപ്പെടില്ല.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> റെക്കോർഡിംഗുകൾ ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്. പൊരുത്തക്കേടുകൾ ഉള്ളതിനാൽ മറ്റ് പരമ്പരകളുടെ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> എപ്പിസോഡുകൾ റെക്കോർഡുചെയ്യപ്പെടില്ല.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> എന്ന പരമ്പരയുടെ <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> റെക്കോർഡിംഗ് ഷെഡ്യൂൾ ചെയ്തിട്ടുണ്ട്. പൊരുത്തക്കേടുകൾ ഉള്ളതിനാൽ മറ്റ് പരമ്പരകളുടെ <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> എപ്പിസോഡുകൾ റെക്കോർഡുചെയ്യപ്പെടില്ല.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"റെക്കോർഡുചെയ്ത പ്രോഗ്രാം കണ്ടെത്തിയില്ല."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"ബന്ധപ്പെട്ട റെക്കോർഡിംഗുകൾ"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(പ്രോഗ്രാം വിവരണമില്ല)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d റെക്കോർഡിംഗുകൾ</item>
       <item quantity="one">%1$d റെക്കോർഡിംഗ്</item>
@@ -334,6 +339,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"സീരീസ് റെക്കോർഡുചെയ്യുന്നത് നിർത്തണോ?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"റെക്കോർഡുചെയ്ത എപ്പിസോഡുകൾ DVR ലൈബ്രറിയിൽ ലഭ്യമാകുന്നത് തുടരും."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"നിർത്തുക"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"എപ്പിസോഡുകളൊന്നും ഇപ്പോൾ പ്രക്ഷേപണം ചെയ്യുന്നില്ല."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"എപ്പിസോഡുകളൊന്നും ലഭ്യമല്ല.\nലഭ്യമായിക്കഴിഞ്ഞാൽ അവ റെക്കോർഡ് ചെയ്യപ്പെടും."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d മിനിറ്റ്)</item>
@@ -345,4 +351,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ഇന്ന്"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> നാളെ"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"സ്കോർ"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"റെക്കോർഡുചെയ്ത പ്രോഗ്രാമുകൾ"</string>
 </resources>
diff --git a/res/values-mn-v23/strings.xml b/res/values-mn-rMN-v23/strings.xml
similarity index 100%
rename from res/values-mn-v23/strings.xml
rename to res/values-mn-rMN-v23/strings.xml
diff --git a/res/values-mn/arrays.xml b/res/values-mn-rMN/arrays.xml
similarity index 100%
rename from res/values-mn/arrays.xml
rename to res/values-mn-rMN/arrays.xml
diff --git a/res/values-mn/rating_system_strings.xml b/res/values-mn-rMN/rating_system_strings.xml
similarity index 100%
rename from res/values-mn/rating_system_strings.xml
rename to res/values-mn-rMN/rating_system_strings.xml
diff --git a/res/values-mn/strings.xml b/res/values-mn-rMN/strings.xml
similarity index 78%
rename from res/values-mn/strings.xml
rename to res/values-mn-rMN/strings.xml
index e99f8a0..3416ea8 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"моно"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"стерео"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Play хяналт"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Саяхны сувгууд"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Сувгууд"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"ТВ-н сонголтууд"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP Сонголтууд"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Энэ сувагт тоглуулах хяналтыг ашиглах боломжгүй байна"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Тоглуулах эсвэл түр зогсоох"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Хурдан урагшлуулах"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Хаалттай капшн"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Дэлгэцийн горим"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Идэвхтэй"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Идэвхгүй"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Мульти-аудио"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Нэмж суваг авах"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Тохиргоо"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Эх сурвалж"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Солих"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Идэвхтэй"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Идэвхгүй"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Дуу"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Үндсэн"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP цонх"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Байрлал"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Баруун доод"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Баруун дээд"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Зүүн дээд"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Зүүн доод"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Зэрэгцсэн"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Хэмжээ"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Том"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Жижиг"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Оролтын эх үүсвэр"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TВ (Антен /Кабел)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Хөтөлбөрийн мэдээлэл байхгүй"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Мэдээлэл байхгүй"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Хаагдсан суваг"</string>
-    <string name="default_language" msgid="4122326459624337928">"Үл мэдэгдэх хэл"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Үл мэдэгдэх хэл"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Хаалттай тайлбар %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Хаалттай тайлбар"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Идэвхгүй"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Форматыг тааруулах"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Бүлэглэх"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Энэ програмыг блоклосон байна."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Энэ хөтөлбөр үнэлгээгүй байна"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Энэ хөтөлбөрийг <xliff:g id="RATING">%1$s</xliff:g>-ээр үнэлэгдсэн байна"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Оролт нь автомат хайлтыг дэмждэггүй"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\'-н автомат хайлтыг эхлүүлэх боломжгүй"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d суваг нэмсэн</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Суваг нэмэгдээгүй"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Тааруулагч"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Эцэг эхийн хяналт"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Идэвхтэй"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Идэвхгүй"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Бусад улс орон"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Хоосон"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Хоосон"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Үнэлгээгүй"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Үнэлгээгүй хөтөлбөрийг блоклох"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Хоосон"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Хатуу хязгаарлалт"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Дунд хязгаарлалт"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Энэ сувгийг үзэхийн тулд PIN оруулна уу"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Энэ хөтөлбөрийг үзэхийн тулд PIN оруулна уу"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Энэ хөтөлбөр нь <xliff:g id="RATING">%1$s</xliff:g> үнэлгээтэй байна. Энэ хөтөлбөрийг үзэхийн тулд ПИН-ээ оруулна уу."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Энэ хөтөлбөр үнэлгээгүй байна. Энэ хөтөлбөрийг үзэхийн тулд ПИН-ээ оруулна уу"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Өөрийн PIN оруулна уу"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Эцэг эхийн хяналт тохируулахын тулд PIN үүсгээрэй"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Шинэ PIN оруулна уу"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Энэ PIN буруу байна. Дахин оролдоно уу."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Дахин оролдоно уу, PIN таарахгүй байна"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"ЗИП кодоо оруулна уу."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"ТВ сувагт хөтөлбөрийн хуваарийг бүрнээр нь олгохын тулд Шууд сувгийн апп ЗИП код ашиглах болно."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"ЗИП кодоо оруулна уу"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"ЗИП код буруу байна"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Тохиргоо"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Сувгийн жагсаалтыг тохируулах"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"ТВ хөтөлбөрт оруулах сувгуудыг сонгоно уу"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Сувгийн эх сурвалж"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Шинэ суваг боломжтой байна"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Эцэг эхийн хяналт"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Нөхөж үзэх"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Шууд хөтөлбөрийг үзэж байх үедээ бичсэнээр түр зогсоох эсвэл ухрааж үзэх боломжтой.\nСануулга: Энэ нь санг эрчимтэй ашигладаг тул дотоод сангийн багтаамжийг бууруулна."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Нээлттэй эхийн лиценз"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Нээлттэй эхийн лиценз"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Санал хүсэлт илгээх"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Хувилбар"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Энэ сувгийг үзэхийн тулд Баруун товчийг дараад өөрийн PIN-г оруулна уу"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Энэ хөтөлбөрийг үзэхийн тулд Баруун товчийг дараад өөрийн PIN-г оруулна уу"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Энэ хөтөлбөр үнэлгээгүй байна.\nЭнэ хөтөлбөрийг үзэхийн тулд Баруун товчийг дараад ПИН-ээ оруулна уу."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Энэ хөтөлбөр <xliff:g id="RATING">%1$s</xliff:g> үнэлгээтэй байна.\nэнэ хөтөлбөрийг үзэхийн тулд Баруун товчийг дараад өөрийн PIN-г оруулна уу."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Энэ сувгийг үзэхийн тулд үндсэн шууд ТВ-н апп-г ашиглаарай,"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Энэ хөтөлбөрийг үзэхийн тулд үндсэн шууд ТВ-н апп ашиглаарай."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Энэ хөтөлбөр үнэлгээгүй байна.\nЭнэ хөтөлбөрийг үзэхийн тулд өгөгдмөл Шууд ТВ аппыг ашиглана уу."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Энэ хөтөлбөр нь <xliff:g id="RATING">%1$s</xliff:g> үнэлгээтэй.\nЭнэ хөтөлбөрийг үзэхийн тулд үндсэн шууд ТВ-н апп-г ашиглаарай."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Хөтөлбөр хориглогдсон"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Энэ хөтөлбөр үнэлгээгүй байна"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Энэ хөтөлбөрийг <xliff:g id="RATING">%1$s</xliff:g>-ээр үнэлэгдсэн байна"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Зөвхөн аудио"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Дохио муу"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"ТВ цэс рүү хандахын тулд "<b>"СОНГОХ гэснийг дарна уу"</b></string>
     <string name="msg_no_input" msgid="3897674146985427865">"ТВ оролт олдсонгүй."</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"ТВ оролтыг олж чадахгүй байна."</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP дэмжигдээгүй байна."</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP-тай харуулж болох бэлэн оролт байхгүй байна."</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Дуу тохируулагчийн төрөл тохирохгүй байна. Зурагтын оролтын дуу тохируулагчийн төрөлд зориулан Шууд Сувгуудын апликейшнийг эхлүүл."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Дуу тааруулж чадсангүй."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Энэ үйлдлийг гүйцэтгэх апп олдсонгүй."</string>
@@ -224,6 +215,8 @@
       <item quantity="other">%1$d бичлэгийг товлосон</item>
       <item quantity="one">%1$d бичлэгийг товлосон</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Бичлэгийг цуцлах"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Дүрс бичихийг зогсоох"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Үзэх"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Эхнээс нь тоглуулах"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Үргэлжлүүлэн тоглуулах"</string>
@@ -256,9 +249,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Олон хөтөлбөрийг зэрэг бичихээр сонгосон тохиолдолд зөвхөн өндөр ач холбогдолтой хөтөлбөрийг бичнэ."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Хадгалах"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Нэг удаагийн бичлэг өндөр ач холбогдолтой"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Цуцлах"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Цуцлах"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Мартах"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Зогсоох"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Бичих хуваарийг харах"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Зөвхөн энэ хөтөлбөр"</string>
@@ -268,25 +258,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Оронд нь үүнийг бичих"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Энэ бичлэгийг цуцлах"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Одоо үзэх"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Бичлэгийг устгах..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Дүрс бичих боломжтой"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Дүрс бичихээр товлосон"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Дүрс бичих боломжгүй"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Бичиж байна"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Бичиж чадсангүй"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Бичлэгийн хуваарь үүсгэхийн тулд хөтөлбөрийг уншиж байна"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Хөтөлбөрийг уншиж байна"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Хөтөлбөрийг уншиж байна"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Сүүлийн бичлэгийг харах"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>-г бичиж чадсангүй."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>-г бичиж чадсангүй."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>-г бичиж чадсангүй."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Багтаамж хангалтгүйн улмаас <xliff:g id="PROGRAMNAME">%1$s</xliff:g>-г бичиж чадсангүй."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Багтаамж хангалтгүйн улмаас <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>-г бичиж чадсангүй."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Багтаамж хангалтгүйн улмаас <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>-г бичиж чадсангүй."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR-д илүү багтаамж шаардлагатай"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Та DVR-р хөтөлбөр бичих боломжтой болно. Гэсэн хэдий ч таны төхөөрөмжид DVR ажиллуулах хангалттай багтаамж алга. <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>гигабайт, эсвэл үүнээс дээш багтаамжтай гадаад драйв холбож, үүнийг төхөөрөмжийн сан болгож хэлбэршүүлэхийн тулд зааврыг дагана уу."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Та DVR-р хөтөлбөр бичих боломжтой болно. Гэсэн хэдий ч таны төхөөрөмжид DVR ажиллуулах хангалттай багтаамж алга. <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>гигабайт, эсвэл үүнээс дээш багтаамжтай гадаад драйв холбож, үүнийг төхөөрөмжийн сан болгож хэлбэршүүлэхийн тулд зааврыг дагана уу."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Хангалттай сан алга"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Сангийн багтаамж хангалтгүй байгаа тул энэ хөтөлбөрийг бичихгүй. Зарим шаардлагагүй бичлэгийг устгана уу."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Сан алга"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR-н ашигласан зарим сан алга. DVR-г дахин идэвхжүүлэхээс өмнө ашигласан гадаад драйвыг холбоно уу. Хэрэв сан байхгүй бол үүнийг мартах боломжтой."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Санг мартах уу?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Таны бичсэн агуулга, хуваарь устах болно."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Бичлэгийг зогсоох уу?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Бичсэн агуулгыг хадгална."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>-н бичлэгийг энэ хөтөлбөртэй зөрчилдөж байгаа тул зогсоох болно. Бичсэн агуулгыг хадгална."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Бичихээр товлосон ч зөрчилтэй байна"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Бичлэг эхлүүлсэн хэдий ч зөрчилтэй байна"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>-г бичих болно."</string>
@@ -304,17 +297,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Үүнтэй ижил хөтөлбөрийг <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>-д бичихээр товлосон байна."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Аль хэдийн бичсэн"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Энэ хөтөлбөрийг аль хэдийн бичсэн байна. Энэ нь DVR санд боломжтой."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Цувралын бичлэгийг товлосон"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> бичлэг товлосон.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> бичлэг товлосон.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> бичлэг товлосон. Тэдгээрийн <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>-г зөрчлийн улмаас бичихгүй.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> бичлэг товлосон. Үүнийг зөрчлийн улмаас бичихгүй.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> бичлэг товлосон. Энэ болон бусад цувралын <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ангийг зөрчлийн улмаас бичихгүй.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> бичлэг товлосон. Энэ болон бусад цувралын <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ангийг зөрчлийн улмаас бичихгүй.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> бичлэг товлосон. Бусад цувралын 1 ангийг зөрчлийн улмаас бичихгүй.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> бичлэг товлосон. Бусад цувралын 1 ангийг зөрчлийн улмаас бичихгүй.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> бичлэг товлосон. Бусад цувралын <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ангийг зөрчлийн улмаас бичихгүй.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>-н <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> бичлэг товлосон. Бусад цувралын <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ангийг зөрчлийн улмаас бичихгүй.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Бичсэн хөтөлбөр олдсонгүй."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Холбоотой бичлэг"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Хөтөлбөрийн тодорхойлолт алга)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d бичлэг</item>
       <item quantity="one">%1$d бичлэг</item>
@@ -334,6 +339,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Цувралыг бичихээ зогсоох уу?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Бичсэн цувралыг DVR санд хадгална."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Зогсоох"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Одоо ямар ч ангийг бичээгүй байна."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Ямар ч анги алга.\nТэд боломжтой болсон үедээ бичих болно."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d минут)</item>
@@ -345,4 +351,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"өнөөдрийн <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Маргаашийн <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Оноо"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Бичигдсэн хөтөлбөр"</string>
 </resources>
diff --git a/res/values-mr-v23/strings.xml b/res/values-mr-rIN-v23/strings.xml
similarity index 100%
rename from res/values-mr-v23/strings.xml
rename to res/values-mr-rIN-v23/strings.xml
diff --git a/res/values-mr/arrays.xml b/res/values-mr-rIN/arrays.xml
similarity index 100%
rename from res/values-mr/arrays.xml
rename to res/values-mr-rIN/arrays.xml
diff --git a/res/values-mr/rating_system_strings.xml b/res/values-mr-rIN/rating_system_strings.xml
similarity index 100%
rename from res/values-mr/rating_system_strings.xml
rename to res/values-mr-rIN/rating_system_strings.xml
diff --git a/res/values-mr/strings.xml b/res/values-mr-rIN/strings.xml
similarity index 77%
rename from res/values-mr/strings.xml
rename to res/values-mr-rIN/strings.xml
index 1888e9d..83d8dd4 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"एक"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"स्टिरिओ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"प्ले नियंत्रणे"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"अलीकडील चॅनेल"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"चॅनेल"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"टीव्‍ही पर्याय"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP पर्याय"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"या चॅनेलसाठी अनुपलब्ध असलेली नियंत्रणे प्ले करा"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"प्ले करा किंवा विराम द्या"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"फास्ट फॉरवर्ड करा"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"उपशीर्षक"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"प्रदर्शन मोड"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"चालू"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"बंद"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"मल्टी-ऑडिओ"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"अधिक चॅनेल मिळवा"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"सेटिंग्ज"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"स्त्रोत"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"अदलाबदल करा"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"चालू"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"बंद"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ध्वनी"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"मुख्य"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP विंडो"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"लेआउट"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"तळाशी उजवीकडे"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"शीर्षस्थानी उजवीकडे"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"शीर्षस्थानी डावीकडे"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"तळाशी डावीकडे"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"शेजारी शेजारी"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"आकार"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"मोठा"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"लहान"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"इनपुट स्त्रोत"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"टीव्ही (अँटेना/केबल)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"कोणतीही कार्यक्रम माहिती नाही"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"कोणतीही माहिती नाही"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"अवरोधित चॅनेल"</string>
-    <string name="default_language" msgid="4122326459624337928">"अज्ञात भाषा"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"अज्ञात भाषा"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"बंद मथळा %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"बंद मथळा"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"बंद"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"स्वरुपन सानुकूलित करा"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"नुसार गट करा"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"हा कार्यक्रम अवरोधित केला आहे"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"या प्रोग्रामला रेट केलेले नाही"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"हा कार्यक्रम <xliff:g id="RATING">%1$s</xliff:g> रेट केला आहे"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"इनपुट स्वयं-स्‍कॅनला समर्थन देत नाही"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' साठी स्वयं-स्कॅन प्रारंभ करण्‍यात अक्षम"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d चॅनेल जोडले</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"कोणतेही चॅनेल जोडले नाही"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ट्यूनर"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"पालक नियंत्रणे"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"चालू"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"बंद"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"इतर देश"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"कोणतेही नाही"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"काहीही नाही"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"रेट न केलेले"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"रेट न केलेले प्रोग्राम ब्लॉक करा"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"काहीही नाही"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"उच्च निर्बंंध"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"मध्यम निर्बंध"</string>
@@ -123,7 +106,8 @@
     <string name="option_subrating_header" msgid="4637961301549615855">"उप रेटिंग"</string>
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"हे चॅनेल पाहण्‍यासाठी आपला पिन प्रविष्‍ट करा"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"हा कार्यक्रम पाहण्‍यासाठी आपला पिन प्रविष्‍ट करा"</string>
-    <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"हा प्रोग्राम <xliff:g id="RATING">%1$s</xliff:g> रेट केलेला आहे. हा प्रोग्राम पाहण्यासाठी आपला PIN प्रविष्ट करा"</string>
+    <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"हा प्रोग्राम <xliff:g id="RATING">%1$s</xliff:g> रेट केलेला आहे. हा प्रोग्राम पाहण्यासाठी आपला पिन प्रविष्ट करा"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"या प्रोग्रामला रेट केलेले नाही. हा प्रोग्राम पाहण्यासाठी तुमचा पिन टाका"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"आपला पिन प्रविष्‍ट करा"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"पालक नियंत्रणे सेट करण्यासाठी, एक पिन तयार करा"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"नवीन पिन प्रविष्ट करा"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"तो पिन चुकीचा होता. पुन्हा प्रयत्न करा."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"पुन्हा प्रयत्न करा, पिन जुळत नाही"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"आपला पिन कोड प्रविष्ट करा."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"टीव्ही चॅनेलसाठी संपूर्ण कार्यक्रम मार्गदर्शक प्रदान करण्यासाठी थेट चॅनेल अॅप पिन कोड वापरेल."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"आपला पिन कोड प्रविष्ट करा"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"अवैध पिन कोड"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"सेटिंग्ज"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"चॅनेल सूची सानुकूल करा"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"आपल्या कार्यक्रम मार्गदर्शकासाठी चॅनेल निवडा"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"चॅनेल स्त्रोत"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"नवीन चॅनेल उपलब्ध आहेत"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"पालक नियंत्रणे"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"पहात असताना रेकॉर्ड करा ज्यामुळे आपण थेट प्रोग्रामांना विराम देऊ किंवा ते रिवाइंड करू शकता.\nचेतावणी: हे संचयाचा अत्याधिक वापर करून कदाचित अंतर्गत संचयाचे आयुष्य कमी करू शकते."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"मुक्त स्त्रोत परवाने"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"मुक्त स्त्रोत परवाने"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"अभिप्राय पाठवा"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"आवृत्ती"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"हे चॅनेल पाहण्यासाठी, उजवे दाबा आणि आपला पिन प्रविष्‍ट करा"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"हा कार्यक्रम पाहण्‍यासाठी, उजवे दाबा आणि आपला पिन प्रविष्‍ट करा"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"या प्रोग्रामला रेट केलेले नाही.\nहा प्रोग्राम पाहण्यासाठी उजवीकडे दाबा आणि तुमचा पिन टाका"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"हा कार्यक्रम <xliff:g id="RATING">%1$s</xliff:g> रेट केला आहे.\n हा कार्यक्रम पाहण्‍यासाठी, उजवे दाबा आणि आपला पिन प्रविष्‍ट करा."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"हे चॅनेल पाहण्यासाठी, डीफॉल्ट थेट टीव्ही अॅप वापरा."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"हा प्रोग्राम पाहण्यासाठी, डीफॉल्ट थेट टीव्ही अॅप वापरा."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"या प्रोग्रामला रेट केलेले नाही.\nहा प्रोग्राम पाहण्यासाठी डीफॉल्ट लाइव्ह टीव्ही अ‍ॅप वापरा."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"हा प्रोग्राम <xliff:g id="RATING">%1$s</xliff:g> रेट केलेला आहे.\nहा प्रोग्राम पाहण्यासाठी, डीफॉल्ट थेट टीव्ही अॅप वापरा."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"कार्यक्रम अवरोधित केला आहे"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"या प्रोग्रामला रेट केलेले नाही"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"हा कार्यक्रम <xliff:g id="RATING">%1$s</xliff:g> रेट केला आहे"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"फक्त ऑडिओ"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"खराब सिग्नल"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"टीव्ही मेनूवर प्रवेश करण्यासाठी "<b>"निवडा दाबा"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"कोणतेही टीव्ही इनपुट आढळले नाही"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"टीव्ही इनपुट शोधू शकत नाही"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP समर्थित नाही"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP सह दर्शविले जाऊ शकते असे कोणतेही उपलब्ध इनपुट नाही"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ट्यूनर प्रकार अनुकूल नाही. कृपया ट्यूनर प्रकार टीव्ही इनपुटसाठी थेट चॅनेल अॅप लाँच करा."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ट्यून अयशस्वी झाले"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ही क्रिया हाताळण्यासाठी कोणताही अ‍ॅप आढळला नाही."</string>
@@ -191,7 +182,7 @@
     <string name="msg_back_key_guide" msgid="7404682718828721924">"बॅक की कनेक्ट केलेल्या डिव्हाइससाठी आहे. बाहेर पडण्यासाठी मुख्यपृष्ठ बटण दाबा."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"थेट चॅनेलना टीव्ही सूचींचे वाचन करण्यासाठी परवानगीची आवश्यकता आहे."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"आपले स्रोत सेट करा"</string>
-    <string name="setup_sources_description" msgid="5695518946225445202">"थेट चॅनेल पारंपारिक TV चॅनेलच्या अनुभवास अॅप्सने प्रदान केलेल्या प्रवाहित केलेल्या चॅनेलसह एकत्रित करतात. \n\nआधीपासून स्थापित केलेले चॅनेल स्रोत सेट करून प्रारंभ करा किंवा थेट चॅनेल प्रदान करणार्‍या आणखी अॅप्ससाठी Google Play स्टोअर ब्राउझ करा."</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"थेट चॅनेल पारंपारिक TV चॅनेलच्या अनुभवास अॅप्सने प्रदान केलेल्या प्रवाहित केलेल्या चॅनेलसह एकत्रित करतात. \n\nआधीपासून इंस्टॉल केलेले चॅनेल स्रोत सेट करून प्रारंभ करा किंवा थेट चॅनेल प्रदान करणार्‍या आणखी अॅप्ससाठी Google Play स्टोअर ब्राउझ करा."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"रेकॉर्डिंग आणि अनुसूची"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 मिनिटे"</string>
     <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 मिनिटे"</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d रेकॉर्डिंगची अनुसूची केली</item>
       <item quantity="other">%1$d रेकॉर्डिंगची अनुसूची केली</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"रेकॉर्डिंग रद्द करा"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"रेकॉर्डिंग थांबवा"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"पहा"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"सुरूवातीपासून प्ले करा"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"प्ले करणे पुनः सुरु करा"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"एकाच वेळी रेकॉर्ड करण्यासाठी खूप जास्त प्रोग्राम असतात तेव्हा, केवळ अधिक प्राधान्ये असलेले प्रोग्राम रेकॉर्ड केले जातील."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"जतन करा"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"एक-वेळ रेकॉर्डिंगला सर्वोच्च प्राधान्य आहे"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"रद्द करा"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"रद्द करा"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"विसरा"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"थांबा"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"रेकॉर्डिंग अनुसूची पहा"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"हा एक कार्यक्रम"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"त्याऐवजी हे रेकॉर्ड करा"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"हे रेकॉर्डिंग रद्द करा"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"आता पहा"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"रेकॉर्डिंग हटवा..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"रेकॉर्ड करण्यायोग्य"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"रेकॉर्डिंग अनुसूचित केले"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"रेकॉर्डिंग संबंधी विरोध"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"रेकॉर्डिंग"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"रेकॉर्डिंग अयशस्वी झाले"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"रेकॉर्डिंग अनुसूची तयार करण्यासाठी प्रोग्राम वाचत आहे"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"वाचन कार्यक्रम"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"वाचन कार्यक्रम"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"अलीकडील रेकॉर्डिंग पहा"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> चे रेकॉर्डिंग अपूर्ण आहे."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> आणि <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> चे रेकॉर्डिंग अपूर्ण आहे."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> आणि <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> चे रेकॉर्डिंग अपूर्ण आहे."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"अपुर्‍या संचयामुळे <xliff:g id="PROGRAMNAME">%1$s</xliff:g> चे रेकॉर्डिंग पूर्ण झाले नाही."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"अपुर्‍या संचयामुळे <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> आणि <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> चे रेकॉर्डिंग पूर्ण झाले नाही."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"अपुर्‍या संचयामुळे <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> चे रेकॉर्डिंग पूर्ण झाले नाही."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR साठी आणखी संचय आवश्यक आहे"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"आपण DVR ने प्रोग्राम रेकॉर्ड करण्यात सक्षम असाल. तथापि DVR ने कार्य करण्यासाठी आपल्या डिव्हाइसवर आता पुरेसा संचय नाही. कृपया <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB किंवा त्यापेक्षा मोठ्या बाह्य ड्राइव्हशी कनेक्ट करा आणि त्यास डिव्हाइस संचय म्हणून स्वरूपित करण्‍यासाठी चरणांचे अनुसरण करा."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"आपण DVR ने प्रोग्राम रेकॉर्ड करण्यात सक्षम असाल. तथापि DVR ने कार्य करण्यासाठी आपल्या डीव्हाइसवर आता पुरेसा संचय नाही. कृपया <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB किंवा त्यापेक्षा मोठ्या बाह्य ड्राइव्हशी कनेक्ट करा आणि त्यास डीव्हाइस संचय म्हणून स्वरूपित करण्‍यासाठी चरणांचे अनुसरण करा."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"पुरेसा संचय नाही"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"पुरेसा संचय नसल्याने हा कार्यक्रम रेकॉर्ड केला जाणार नाही. काही विद्यमान रेकॉर्डिंग हटवून पहा."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"संचय गहाळ आहे"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR ने वापरलेला काही संचय गहाळ आहे. कृपया DVR पुन्हा सक्षम करण्‍यासाठी आपण पूर्वी वापरलेला बाह्य ड्राइव्ह कनेक्ट करा. वैकल्पिकपणे, यापुढे संचय उपलब्ध नसल्यास आपण तो विसरणे निवडू शकता."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"संचय विसरलात?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"आपली सर्व रेकॉर्ड केलेली सामग्री आणि अनुसूची गमावल्या जातील."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"रेकॉर्डिंग थांबवायचे?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"रेकॉर्ड केलेली सामग्री जतन केली जाईल."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> चे रेकॉर्डिंग थांबवले जाईल कारण ते या कार्यक्रमासह संघर्ष करते. रेकॉर्ड केलेली सामग्री जतन केली जाईल."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"रेकॉर्डिंगची अनुसूची केली परंतु त्यासंबंधी विरोध आहेत"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"रेकॉर्डिंग सुरू झाली परंतु त्यासंबंधी विरोध आहेत"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> रेकॉर्ड केला जाईल."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> रोजी रेकॉर्ड करण्यासाठी तोच कार्यक्रम आधीच शेड्यूल केला आहे."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"आधीच रेकॉर्ड केला आहे"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"हा कार्यक्रम आधीच रेकॉर्ड केला गेला आहे. तो DVR लायब्ररीमध्ये उपलब्ध आहे."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"मालिका रेकॉर्डिंग अनुसूचित केले"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली. त्यांंच्यापैकी <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> विरोधांमुळे रेकॉर्ड केले जाणार नाहीत.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली. त्यांंच्यापैकी <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> विरोधांमुळे रेकॉर्ड केले जाणार नाहीत.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली. या मालिकेचे आणि अन्य मालिकांचे <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> भाग विरोधांमुळे रेकॉर्ड केले जाणार नाहीत.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली. या मालिकेचे आणि अन्य मालिकांचे <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> भाग विरोधांमुळे रेकॉर्ड केले जाणार नाहीत.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली. अन्य मालिकांचा 1 भाग विरोधांमुळे रेकॉर्ड केला जाणार नाही.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली. अन्य मालिकांचा 1 भाग विरोधांमुळे रेकॉर्ड केला जाणार नाही.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली. अन्य मालिकेचे <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> भाग विरोधांंमुळे रेकॉर्ड केले जाणार नाहीत.</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> साठी <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रेकॉर्डिंगची अनुसूची केली गेली. अन्य मालिकेचे <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> भाग विरोधांंमुळे रेकॉर्ड केले जाणार नाहीत.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"रेकॉर्ड केलेला प्रोग्राम सापडला नाही."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"संबंधित रेकॉर्डिंग"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(कोणत्याही प्रोग्रामचे वर्णन नाही)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d रेकॉर्डिंग</item>
       <item quantity="other">%1$d रेकॉर्डिंग</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"मालिका रेकॉर्ड करणे थांबवायचे?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"रेकॉर्ड केलेले भाग DVR लायब्ररी मध्ये उपलब्ध राहतील."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"थांबा"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"आता कोणत्याही भागांचे प्रसारण होत नाही."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"कोणतेही भाग उपलब्ध नाहीत.\nते उपलब्ध झाल्यावर रेकॉर्ड केले जातील."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d मिनिट)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"आज <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"उद्या <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"गुणसंख्‍या"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"रेकॉर्ड केलेले प्रोग्राम"</string>
 </resources>
diff --git a/res/values-ms-v23/strings.xml b/res/values-ms-rMY-v23/strings.xml
similarity index 100%
rename from res/values-ms-v23/strings.xml
rename to res/values-ms-rMY-v23/strings.xml
diff --git a/res/values-ms/arrays.xml b/res/values-ms-rMY/arrays.xml
similarity index 100%
rename from res/values-ms/arrays.xml
rename to res/values-ms-rMY/arrays.xml
diff --git a/res/values-ms/rating_system_strings.xml b/res/values-ms-rMY/rating_system_strings.xml
similarity index 100%
rename from res/values-ms/rating_system_strings.xml
rename to res/values-ms-rMY/rating_system_strings.xml
diff --git a/res/values-ms/strings.xml b/res/values-ms-rMY/strings.xml
similarity index 78%
rename from res/values-ms/strings.xml
rename to res/values-ms-rMY/strings.xml
index 816dee3..91716d8 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Kawalan main"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Saluran terbaru"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Saluran"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Pilihan TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Pilihan PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Kawalan main tidak tersedia untuk saluran ini"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Main atau jeda"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Mara laju"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Sari kata"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Mod paparan"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Hidupkan"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Matikan"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Berbilang audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Dptkn lg saluran"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Tetapan"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Sumber"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Silih"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Hidupkan"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Matikan"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Bunyi"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Utama"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Tetingkap PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Reka Letak"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Kanan bawah"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Kanan atas"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Kiri atas"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Kiri bawah"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Bersebelahan"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Saiz"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Besar"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Kecil"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Sumber input"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Maklumat program tiada"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Tiada maklumat"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Saluran disekat"</string>
-    <string name="default_language" msgid="4122326459624337928">"Bahasa tidak diketahui"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Bahasa tidak diketahui"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Sari kata %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Sari kata"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Dimatikan"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Sesuaikan format"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Kumpulkan mengikut"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Rancangan ini disekat"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Rancangan ini tidak dinilai"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Rancangan ini diberi rating <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Input tidak menyokong autoimbas"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Tidak dapat memulakan autoimbas untuk \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d saluran ditambahkan</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Tiada saluran ditambahkan"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Penala"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Kawalan ibu bapa"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Hidup"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Dimatikan"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Negara lain"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Tiada"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Tiada"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Tidak dinilai"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Sekat rancangan yg tdk dinilai"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Tiada"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Sekatan ketat"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Sekatan sederhana"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Masukkan PIN anda untuk menonton saluran ini"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Masukkan PIN anda untuk menonton rancangan ini"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Rancangan ini diberi rating <xliff:g id="RATING">%1$s</xliff:g>. Masukkan PIN anda untuk menonton rancangan ini"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Rancangan ini tidak dinilai. Masukkan PIN anda untuk menonton rancangan ini"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Masukkan PIN anda"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Untuk menetapkan kawalan ibu bapa, buat PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Masukkan PIN baharu"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN itu salah. Cuba lagi."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Cuba lagi, PIN tidak sepadan"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Masukkan Poskod anda."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Apl Saluran Langsung akan menggunakan Poskod untuk menyediakan panduan lengkap rancangan saluran TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Masukkan Poskod anda"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Poskod tidak sah"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Tetapan"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Sesuaikan senarai saluran"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Pilih saluran untuk panduan rancangan anda"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Sumber saluran"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Saluran baharu tersedia"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Kawalan ibu bapa"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Anjakan masa"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Rakam semasa menonton supaya anda boleh menjeda atau mandir rancangan langsung.\nAmaran: Tindakan ini boleh mengurangkan hayat storan dalaman melalui penggunaan intensif storan itu."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Lesen sumber terbuka"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Lesen sumber terbuka"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Hantar maklum balas"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versi"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Untuk menonton saluran ini, tekan Kanan dan masukkan PIN anda"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Untuk menonton rancangan ini, tekan Kanan dan masukkan PIN anda"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Rancangan ini tidak dinilai.\nUntuk menonton rancangan ini, tekan Kanan kemudian masukkan PIN anda"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Rancangan ini diberi rating <xliff:g id="RATING">%1$s</xliff:g>.\nUntuk menonton rancangan ini, tekan Kanan, kemudian masukkan PIN anda."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Untuk menonton saluran ini, gunakan apl lalai TV Langsung."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Untuk menonton program ini, gunakan apl lalai TV Langsung."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Rancangan ini tidak dinilai.\nUntuk menonton rancangan ini, gunakan apl lalai TV Langsung."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Atur cara ini telah dinilai <xliff:g id="RATING">%1$s</xliff:g>.\nUntuk menonton program ini, gunakan apl lalai TV Langsung."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Rancangan disekat"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Rancangan ini tidak dinilai"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Rancangan ini diberi rating <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audio sahaja"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Isyarat lemah"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Tekan PILIH"</b>" untuk mengakses menu TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Input TV tidak ditemui"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Tidak menemui input TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP tidak disokong"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Tiada input tersedia yang boleh ditunjukkan dengan PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Jenis penala tidak sesuai; Sila lancarkan apl Saluran Langsung untuk input TV jenis penala."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Penalaan gagal"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Tiada apl ditemui untuk mengendalikan tindakan ini."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d rakaman dijadualkan</item>
       <item quantity="one">%1$d rakaman dijadualkan</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Batalkan rakaman"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Hentikan rakaman"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Tonton"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Mainkan dari mula"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Sbg smula prses main"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Apabila ada terlalu banyak rancangan yang ingin dirakamkan secara serentak, rancangan yang berkeutamaan lebih tinggi sahaja yang akan dirakamkan."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Simpan"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Rakaman bersifat sekali sahaja mendapat keutamaan tertinggi"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Batal"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Batal"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Lupakan"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Berhenti"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Lihat jadual rakaman"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Program ini sahaja"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Sebaliknya rakamkan yang ini"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Batalkan rakaman ini"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Tonton sekarang"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Padam rakaman..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Boleh rakam"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Rakaman dijadualkan"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Konflik rakaman"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Merakam"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Perakaman gagal"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Membaca rancangan untuk membuat jadual rakaman"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Membaca rancangan"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Membaca rancangan"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Lihat rakaman terbaharu"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Rakaman <xliff:g id="PROGRAMNAME">%1$s</xliff:g> tidak lengkap."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Rakaman <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> dan <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> tidak lengkap."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Rakaman <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> dan <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> tidak lengkap."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Rakaman <xliff:g id="PROGRAMNAME">%1$s</xliff:g> tidak lengkap kerana storan tidak mencukupi."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Rakaman <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> dan <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> tidak lengkap kerana storan tidak mencukupi."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Rakaman <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> dan <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> tidak lengkap kerana storan tidak mencukupi."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR memerlukan storan yang lebih besar"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Anda boleh merakam rancangan menggunakan DVR. Walau bagaimanapun storan pada peranti anda kini tidak mencukupi untuk DVR berfungsi. Sila sambungkan pemacu luaran <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB atau lebih besar dan ikut langkah untuk memformat pemacu itu sebagai storan peranti."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Anda boleh merakam rancangan menggunakan DVR. Walau bagaimanapun storan pada peranti anda kini tidak mencukupi untuk DVR berfungsi. Sila sambungkan pemacu luaran <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB atau lebih besar dan ikut langkah untuk memformat pemacu itu sebagai storan peranti."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Storan tidak mencukupi"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Rancangan ini tidak akan dirakamkan kerana storan tidak mencukupi. Cuba padamkan beberapa rakaman sedia ada."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Storan hilang"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Beberapa storan yang digunakan oleh DVR telah hilang. Sila sambungkan pemacu luaran yang anda gunakan sebelum ini untuk mendayakan semula DVR. Secara alternatif, anda boleh memilih untuk melupakan storan jika storan itu tidak lagi tersedia."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Lupakan storan?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Semua kandungan dan jadual anda yang dirakamkan akan hilang."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Berhenti merakam?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Kandungan yang dirakamkan akan disimpan."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Rakaman <xliff:g id="PROGRAMNAME">%1$s</xliff:g> akan dihentikan kerana wujud konflik dengan rancangan ini. Kandungan yang dirakamkan akan disimpan."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Rakaman dijadualkan tetapi wujud konflik"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Rakaman telah bermula tetapi wujud konflik"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> akan dirakamkan."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Rancangan yang sama telah dijadualkan akan dirakamkan pada <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Sudah dirakamkan"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Rancangan ini telah dirakamkan dan tersedia di pustaka DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Rakaman siri telah dijadualkan"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> daripadanya tidak akan dirakamkan kerana berlaku konflik.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Rakaman ini tidak akan dijalankan kerana berlaku konflik.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episod siri ini dan siri yang lain tidak akan dirakamkan kerana berlaku konflik.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episod siri ini dan siri yang lain tidak akan dirakamkan kerana berlaku konflik.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episod siri yang lain tidak akan dirakamkan kerana berlaku konflik.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 episod siri yang lain tidak akan dirakamkan kerana berlaku konflik.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episod siri yang lain tidak akan dirakamkan kerana berlaku konflik.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> rakaman telah dijadualkan untuk <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episod siri yang lain tidak akan dirakamkan kerana berlaku konflik.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Program yang dirakam tidak ditemui."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Rakaman yang berkaitan"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Tiada perihalan program)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d rakaman</item>
       <item quantity="one">%1$d rakaman</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Berhenti merakam siri?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Episod yang dirakamkan akan kekal tersedia dalam pustaka DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Berhenti"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Tiada episod sedang dalam siaran."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Tiada episod yang tersedia.\nEpisod ini akan dirakamkan apabila sudah tersedia."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minit)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> hari ini"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> esok"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Markah"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Rancangan yang Dirakamkan"</string>
 </resources>
diff --git a/res/values-my-v23/strings.xml b/res/values-my-rMM-v23/strings.xml
similarity index 100%
rename from res/values-my-v23/strings.xml
rename to res/values-my-rMM-v23/strings.xml
diff --git a/res/values-my/arrays.xml b/res/values-my-rMM/arrays.xml
similarity index 100%
rename from res/values-my/arrays.xml
rename to res/values-my-rMM/arrays.xml
diff --git a/res/values-my/rating_system_strings.xml b/res/values-my-rMM/rating_system_strings.xml
similarity index 100%
rename from res/values-my/rating_system_strings.xml
rename to res/values-my-rMM/rating_system_strings.xml
diff --git a/res/values-my/strings.xml b/res/values-my-rMM/strings.xml
similarity index 76%
rename from res/values-my/strings.xml
rename to res/values-my-rMM/strings.xml
index 1ab6baf..c647540 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"မိုနို"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"စတီရီယို"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Play ထိန်းချုပ်မှုများ"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"မကြာမီက ချာနယ်"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ချာနယ်များ"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV ရွေးစရာများ"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP ရွေးချယ်စရာများ"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ဤလိုင်းအတွက် အဖွင့်ထိန်းချုပ်ခြင်းများ မရနိုင်ပါ"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"ဖွင့်ပါ သို့မဟုတ် ခဏရပ်ပါ"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"ရှေ့သို့ အမြန်သွားရန်"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"စာတမ်းထိုးများ"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"မြင်ကွင်း မုဒ်"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"ဖွင့်ထား"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"ပိတ်ထား"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"အသံစုံ"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"နောက်ထပ်ချန်နယ်များ ရယူရန်"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"ဆက်တင်များ"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"ရင်းမြစ်"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"လဲပြောင်းသည်"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"ဖွင့်ထား"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"ပိတ်ထား"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"အသံ"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"အဓိက"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP ဝင်းဒိုး"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"အဆင်အပြင်"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"အောက်ညာ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"အပေါ်ညာ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"အပေါ်ဘယ်"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"အောက်ဘယ်"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"ကပ်လျက်"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"ဆိုက်"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"ကြီး"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"သေး"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"ထည့်သွင်းမှု ရင်းမြစ်"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"တီဗီ (ဧရီယာတိုင်/ကြိုး)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"အစီအစဉ် အချက်အလက်များ မရှိ"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"သတင်းအချက်အလက် မရှိပါ"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"ပိတ်ဆို့ ချာနယ်"</string>
-    <string name="default_language" msgid="4122326459624337928">"အမည်မသိဘာသာစကား"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"အမည်မသိဘာသာစကား"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"စာတန်းထိုး %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"စာတမ်းထိုးများ"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"ပိတ်ထား"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"စိတ်ကြိုက်ပုံစံချရန်"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"အုပ်စုဖွဲ့မှု"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"ဤအစီအစဉ်အား ပိတ်ဆို့ထားသည်။"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"ဤအစီအစဉ်ကို အဆင့်မသတ်မှတ်ရသေးပါ"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"ဤအစီအစဉ်သည် အဆင့် <xliff:g id="RATING">%1$s</xliff:g> ရှိ၏"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ထည့်သွင်းမှုက အော်တို-စကင် ပံ့ပိုးမပေး"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' အတွက် အော်တို−စကင် မစနိုင်ပါ"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">ချန်နယ် %1$d ခုပေါင်းထည့်ပြီးပါပြီ</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"ချာနယ်များ ထည့်မထား"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"တျူနား"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"မိဘ ထိန်းချုပ်မှု"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ဖွင့်ရန်"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"ပိတ်ရန်"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"အခြားနိုင်ငံများ"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"မရှိ"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"မရှိ"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"အဆင့် သတ်မှတ်မထားပါ"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"မစိစစ်သောအစီအစဉ်များ ပိတ်ရန်"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"မရှိ"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"ကန့်သတ်ချက်မြှင့်ရန်"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"ကန့်သတ်ချက်များ အလတ်"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"ဒီချာနယ်ကို ကြည့်ရန် သင့် PIN ရိုက်ထည့်ပါ"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"ဒီအစီအစဉ်ကို ကြည့်ရန် သင့် PIN ရိုက်ထည့်ပါ"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"ဤပရိုဂရမ်ကို <xliff:g id="RATING">%1$s</xliff:g> အဆင့်သတ်မှတ်ထားပါသည်။ ဤပရိုဂရမ်ကို ကြည့်ရှုရန် သင့်ပင်နံပါတ်ကို ထည့်ပါ"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"ဤအစီအစဉ်ကို အဆင့်မသတ်မှတ်ရသေးပါ။ ဤအစီအစဉ်ကိုကြည့်ရန် သင်၏ ပင်နံပါတ် ထည့်ပါ။"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"သင့် PIN ရိုက်ထည့်ပါ"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"မိဘ ထိန်းချုပ်မှုကို သတ်မှတ်ရန်၊ PIN ကို ဖန်တီးပါ"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"PIN အသစ်ကို ထည့်သွင်းရန်"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"ထို PIN မှာ မှားနေသည်။ ထပ်ကြိုးစားပါ။"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN မှာ မတိုက်ဆိုင်ပါ၊ ထပ်ပြီး စမ်းပါ။"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"စာတိုက်ကုဒ်ကို ထည့်ပါ။"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"TV ချန်နယ်များအတွက် ပြီးပြည့်စုံသည့် အစီအစဉ်များကို ပံ့ပိုးပေးရန် Live TV က စာတိုက်ကုဒ်ကိုသုံးပါမည်။"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"စာတိုက်ကုဒ်ကို ထည့်ပါ"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"စာတိုက်သင်္က​ေတ မမှန်ပါ"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"ဆက်တင်များ"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"ချန်နယ်စာရင်းကို စိတ်တိုင်းကျပြုပြင်ရန်"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"သင့်ပရိုဂရမ်လမ်းညွှန်အတွက် ချန်နယ်များရွေးချယ်ပါ"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"ချန်နယ် အရင်းအမြစ်များ"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"ချန်နယ်အသစ်များ ရနိုင်ပါသည်"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"မိဘ ထိန်းချုပ်မှု"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"အချိန်ရွှေ့ဆိုင်းခြင်း"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"ကြည့်နေရင်း မှတ်တမ်းတင်ထားပါက တိုက်ရိုက်အစီအစဉ်များကို ခေတ္တရပ်နားနိုင်သလို ပြန်ရစ်ကြည့်နိုင်ပါသည်။\nသတိ− ဤသို့ပြုလုပ်လျှင် သိမ်းဆည်းမှုများစွာ အသုံးပြုခြင်းကြောင့် စက်အတွင်း သိမ်းဆည်းရန်နေရာ၏ သက်တမ်းကို လျော့ကျစေနိုင်ပါသည်။"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"အခမဲ့အရင်းအမြစ်လိုင်စင်များ"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"အခမဲ့ ရင်းမြစ် လိုင်စင်များ"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"အကြံပြုချက် ပေးပို့ပါ"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"ဗားရှင်း"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"ဤချာနယ်ကို ကြည့်ရန်၊ ညာဘက် နှိပ်ပြီး PIN ရိုက်ထည့်ပါ"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"ဤအစီအစဉ်ကို ကြည့်ရန်၊ ညာဘက် နှိပ်ပြီး PIN ရိုက်ထည့်ပါ"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"ဤအစီအစဉ်ကို အဆင့်မသတ်မှတ်ရသေးပါ။\nဤအစီအစဉ်ကို ကြည့်ရန် ညာဘက်သို့ ဖိပြီး ပင်နံပါတ် ထည့်ပါ"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"ဤအစီအစဉ်သည် အဆင့် <xliff:g id="RATING">%1$s</xliff:g> ရှိ၏။ \nဤအစီအစဉ်အား ကြည့်ရန်၊ ညာဘက် နှိပ်ပြီး PIN ရိုက်ထည့်ပါ။"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ဤချန်နယ်ကိုကြည့်ရန်၊ မူလတိုက်ရိုက်လွှင့်သည့်တီဗွီအပ်ဖ်ကို အသုံးပြုပါ။"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"အစီအစဉ်ကိုကြည့်ရန်၊ မူလတိုက်ရိုက်လွှင့်သည့် တီဗွီအပ်ဖ်ကိုအသုံးပြုပါ။"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"ဤအစီအစဉ်ကို အဆင့်မသတ်မှတ်ရသေးပါ။\nဤအစီအစဉ်ကို ကြည့်ရန် မူလ တိုက်ရိုက်လွှင့်နေသော TV အက်ပ်ကို အသုံးပြုပါ။"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"ဤအစီအစဉ်ကို <xliff:g id="RATING">%1$s</xliff:g> သတ်မှတ်ထားသည်။ \nဤအစီအစဉ်ကိုကြည့်ရန်၊ မူလတိုက်ရိုက်လွှင့်သည့် တီဗွီအပ်ဖ်ကိုအသုံးပြုပါ။"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"အစီအစဉ်ကို ပိတ်ဆို့ထား"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"ဤအစီအစဉ်ကို အဆင့်မသတ်မှတ်ရသေးပါ"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"ဤအစီအစဉ်သည် အဆင့် <xliff:g id="RATING">%1$s</xliff:g> ရှိ၏"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"အသံ သီးသန့်"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"လှိုင်းဆွဲအားနည်းသည်"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>" ရွေးချယ်ပါအားနှိပ်ပြီး"</b>" တီဗီမန်နယူးကိုဝင်ရောက်ကြည့်ရှုပါ။"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"တီဗီ ထည့်သွင်းမှု ရှာမတွေ့ပါ။"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"တီဗီ ထည့်သွင်းမှု ရှာမတွေ့နိုင်ပါ။"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP ကို ပံ့ပိုးမထားပါ။"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP နှင့် ပြနိုင်သည့် ထည့်သွင်းစရာ မရှိပါ။"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"သင့်တော်သည့် တျူနာ အမျိုးအစား မဟုတ်ပါ။ တီဗွီ အဝင်ပေါက်အတွက် တိုက်ရိုက်လွှင့် ချန်နယ်များ အက်ပ်အား ဖွင့်ပါ။"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ညှိမှု မအောင်မြင်ပါ"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ဤလုပ်ဆောင်ချက်ကို ကိုင်တွယ်နိုင်သည့် အက်ပ်မရှိပါ။"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">ရိုက်ကူးရန် အစီအစဉ်%1$dခု</item>
       <item quantity="one">ရိုက်ကူးရန် အစီအစဉ်%1$dခု</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"ကူးယူမှု ပယ်ဖျက်မည်"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"ကူးယူမှု ရပ်မည်"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ကြည့်ရန်"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"အစမှနေ၍ ဖွင့်ရန်"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"ဆက်ဖွင့်ရန်"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"တစ်ချိန်တည်းတွင် ဖမ်းယူရမည့်အစီအစဉ် များပြားလွန်းသည့်အခါ ဦးစားပေးမှု ပိုမိုမြင့်မားသည့် အစီအစဉ်များကိုသာ ဖမ်းယူသွားပါမည်။"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"သိမ်းရန်"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"တစ်ကြိမ်တစ်ခါတည်း ဖမ်းယူခြင်းသည် ဦးစားပေးမှုအမြင့်ဆုံးဖြစ်သည်"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"မလုပ်တော့"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"မလုပ်တော့"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"မေ့ပစ်ရန်"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"ရပ်ရန်"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"ဖမ်းယူခြင်းအချိန်ဇယားကို ကြည့်ရန်"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"ဤအစီအစဉ် တစ်ခုတည်း"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"၎င်းအစား ဤတစ်ခုကို ဖမ်းယူပါ"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ဤဖမ်းယူမှုကို ပယ်ဖျက်ရန်"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"ယခုကြည့်ရန်"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ရုပ်သံရိုက်ကူးမှုများ ဖျက်ပါ..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"ရိုက်ကူးနိုင်သည်"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ရိုက်ကူးရေးအတွက် စီစဉ်ထားပါသည်"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ရိုက်ကူးရေးအစီအစဉ်တိုက်နေပါသည်"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"ဖမ်းယူနေသည်"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ဖမ်းယူခြင်း မအောင်မြင်ပါ"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"ရိုက်ကူးရေး အချိန်ဇယားများ သတ်မှတ်ရန် အစီအစဉ်များကို ဖတ်နေသည်"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"ပရိုဂရမ်များကို ဖတ်နေသည်"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"ပရိုဂရမ်များကို ဖတ်နေသည်"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"မကြာသေးမီက ရိုက်ကူးမှုများကို ကြည့်ပါ"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ကို ကူးယူမှု မပြီးဆုံးခဲ့ပါ။"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> နှင့် <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> တို့ကို ကူးယူမှု မပြီးဆုံးခဲ့ပါ။"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>၊ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> နှင့် <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> တို့ကို ကူးယူမှု မပြီးဆုံးခဲ့ပါ။"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"သိုလှောင်ခန်း လုံလောက်မှု မရှိသည့်အတွက် <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ကို ပြီးဆုံးအောင် မကူးယူနိုင်ခဲ့ပါ။"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"သိုလှောင်ခန်း လုံလောက်မှု မရှိသည့်အတွက် <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> နှင့် <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> တို့ကို ပြီးစီးအောင် မကူးယူနိုင်ခဲ့ပါ။"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"သိုလှောင်ခန်း လုံလောက်မှု မရှိသည့်အတွက် <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>၊ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> နှင့် <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> တို့ကို ပြီးစီးအောင် မကူးယူနိုင်ခဲ့ပါ။"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR သည် နောက်ထပ်သိုလှောင်ရန်နေရာလွတ် လိုအပ်နေသည်"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"အစီအစဉ်များကို DVR နှင့် ဖမ်းယူသိမ်းဆည်းထားနိုင်ပါသည်။ သို့သော် DVR ကို အသုံးပြုနိုင်ရန် သင့်စက်ပစ္စည်းတွင် လုံလောက်သော နေရာလွတ် လောလောဆယ်မရှိပါ။ <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>ဂစ်ဂါဘိုက် သို့မဟုတ် ၎င်းနှင့်အထက်ရှိသော ပြင်ပသိုလှောင်ကိရိယာနှင့် ချိတ်ဆက်ပြီး ၎င်းကို သိုလှောင်ခန်းစက်ပစ္စည်းအဖြစ် ပြင်ဆင်သတ်မှတ်ရန် ညွှန်ကြားချက်များအတိုင်း လိုက်နာပါ။"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"အစီအစဉ်များကို DVR နှင့် ဖမ်းယူသိမ်းဆည်းထားနိုင်ပါသည်။ သို့သော် DVR ကို အသုံးပြုနိုင်ရန် သင့်စက်ပစ္စည်းတွင် လုံလောက်သော နေရာလွတ် လောလောဆယ်မရှိပါ။ <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>ဂစ်ဂါဘိုက် သို့မဟုတ် ၎င်းနှင့်အထက်ရှိသော ပြင်ပသိုလှောင်ကိရိယာနှင့် ချိတ်ဆက်ပြီး ၎င်းကို သိုလှောင်ခန်းစက်ပစ္စည်းအဖြစ် ပြင်ဆင်သတ်မှတ်ရန် ညွှန်ကြားချက်များအတိုင်း လိုက်နာပါ။"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"သိုလှောင်ခန်း မလုံလောက်ပါ"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"သိုလှောင်ခန်း လုံလောက်မှုမရှိသည့်အတွက် ဤအစီအစဉ်ကို ရိုက်ကူးမည်မဟုတ်ပါ။ လက်ရှိရိုက်ကူးချက်အချို့ကို ဖျက်ကြည့်ပါ။"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"သိုလှောင်မှုများ ပျောက်ဆုံးနေခြင်း"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR က အသုံးပြုသော သိုလှောင်ခန်းအချို့မှာ ပျောက်ဆုံးနေသည်။ DVR ကို ပြန်ဖွင့်ရန်အတွက် ယခင်က အသုံးပြုခဲ့သော ပြင်ပသုံးအခွေဖွင့်စက်နှင့် ချိတ်ဆက်ပါ။ နောက်တစ်နည်းအနေဖြင့် ၎င်းကို အသုံးပြု၍ မရတော့လျှင် မေ့ပစ်ရန် ရွေးချယ်နိုင်ပါသည်။"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"သိုလှောင်ခန်းကို မေ့ပစ်မလား။"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"သင်မှတ်တမ်းတင်ထားသော အကြောင်းအရာနှင့် အချိန်ဇယားများအားလုံး ဆုံးရှုံးသွားလိမ့်မည်။"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"ရိုက်ကူးခြင်းကို ရပ်လိုပါသလား။"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"ဖမ်းယူထားသည့် အကြောင်းအရာကို သိမ်းဆည်းထားပါမည်။"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ကို ဖမ်းယူခြင်းသည် ဤပရိုဂရမ်နှင့် ပဋိပက္ခများ ဖြစ်နေသောကြောင့် ၎င်းသည် ရပ်တန့်သွားပါမည်။ ဖမ်းယူထားသည့် အကြောင်းအရာကို သိမ်းဆည်းသွားပါမည်။"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ဖမ်းယူရန် စီစဉ်ထားသော်လည်း အချိန်ဇယားတိုက်နေပါသည်"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ဖမ်းယူမှုကို စတင်လိုက်ပါပြီ။ သို့သော် အချိန်ဇယားတိုက်နေပါသည်"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ကို ဖမ်းယူသွားပါမည်။"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"တူညီသည့် ပရိုဂရမ်ကို <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> ၌ ဖမ်းယူရန် စီစဉ်ထားပြီး ဖြစ်ပါသည်။"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"ဖမ်းယူပြီးပါပြီ"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"ဤပရိုဂရမ်ကို ဖမ်းယူပြီးပါပြီ။ ၎င်းကို DVR စာကြည့်တိုက်တွင် ကြည့်ရှုနိုင်ပါသည်။"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"စီးရီးများကို ဖမ်းယူခြင်းကို စီစဉ်ထားပါသည်"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_3">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။</item>
+      <item quantity="one">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_1">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_3">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။ ပဋိပက္ခများ ရှိနေသဖြင့် ၎င်းတို့အနက်မှ <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ခုကို ကူးယူသွားမည် မဟုတ်ပါ။</item>
+      <item quantity="one">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_1">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။ ပဋိပက္ခများ ရှိနေသဖြင့် ၎င်းကို ကူးယူသွားမည် မဟုတ်ပါ။</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_4">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။ ပဋိပက္ခများ ရှိနေသဖြင့် ဤစီးရီးနှင့် အခြားစီးရီးများ၏ ဇာတ်လမ်းပိုင်း <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ပိုင်းကို ကူးယူသွားမည်မဟုတ်ပါ။</item>
+      <item quantity="one">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_1">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။ ပဋိပက္ခများ ရှိနေသဖြင့် ဤစီးရီးနှင့် အခြားစီးရီးများ၏ ဇာတ်လမ်းပိုင်း <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ပိုင်းကို ကူးယူသွားမည်မဟုတ်ပါ။</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_3">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။ ပဋိပက္ခများ ရှိနေသဖြင့် အခြားစီးရီးများ၏ ဇာတ်လမ်းပိုင်း ၁ ပိုင်းကို ကူးယူသွားမည်မဟုတ်ပါ။</item>
+      <item quantity="one">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_1">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။ ပဋိပက္ခများ ရှိနေသဖြင့် အခြားစီးရီးများ၏ ဇာတ်လမ်းပိုင်း ၁ ပိုင်းကို ကူးယူသွားမည်မဟုတ်ပါ။</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_4">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။ ပဋိပက္ခများ ရှိနေသဖြင့် အခြားစီးရီးများ၏ ဇာတ်လမ်းပိုင်း <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ပိုင်းကို ကူးယူသွားမည်မဟုတ်ပါ။</item>
+      <item quantity="one">ရိုက်ကူးမှု <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ခုကို <xliff:g id="SERIESNAME_1">%2$s</xliff:g> အတွက် စီစဉ်ထားပါသည်။ ပဋိပက္ခများ ရှိနေသဖြင့် အခြားစီးရီးများ၏ ဇာတ်လမ်းပိုင်း <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ပိုင်းကို ကူးယူသွားမည်မဟုတ်ပါ။</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"ရိုက်ကူးထားသည့်ပရိုဂရမ်ကို မတွေ့ပါ။"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"ဆက်စပ်နေသည့် ရိုက်ကူးမှုများ"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(ပရိုဂရမ် ဖော်ပြချက်မရှိပါ)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">ရိုက်ပြီးသား %1$d ခု</item>
       <item quantity="one">ရိုက်ပြီးသား %1$d ခု</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"ဇာတ်လမ်းတွဲဖမ်းယူခြင်းကို ရပ်မလား။"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"ဖမ်းယူထားသည့် အပိုင်းများသည် DVR စာကြည့်တိုက်တွင် ရှိနေဦးမည်ဖြစ်သည်။"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"ရပ်ရန်"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ယခု မည်သည့် ဇာတ်လမ်းပိုင်းကိုမျှ လွှင့်နေခြင်း မရှိပါ။"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"အပိုင်းငယ်များ မရနိုင်သေးပါ။\nရနိုင်သည်နှင့် ၎င်းတို့ကို ဖမ်းယူသွားပါမည်။"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d မိနစ်)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"ဒီနေ့ <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"မနက်ဖြန် <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"ရမှတ်"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"ကူးယူထားသော အစီအစဉ်များ"</string>
 </resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index a2cf46c..b9c149a 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Play-kontroller"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Nylige kanaler"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanaler"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV-alternativer"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-alternativer"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Play-kontroller er ikke tilgjengelige for denne kanalen"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Spill av eller sett på pause"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Spol fremover"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Teksting"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Visningsmodus"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"På"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Av"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Flere lydspor"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Få flere kanaler"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Innstillinger"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Kilde"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Bytt"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"På"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Av"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Lyd"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Hovedkontroll"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-vindu"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Utforming"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Nede til høyre"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Oppe til høyre"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Oppe til venstre"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Nede til venstre"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Side om side"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Størrelse"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Stor"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Liten"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Inndatakilde"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenne/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Ingen programinformasjon"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Ingen informasjon"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blokkert kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Ukjent språk"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Ukjent språk"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Teksting %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Teksting for hørselshemmede"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Av"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Tilpass formatering"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Gruppér etter"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Dette programmet er blokkert."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Dette programmet har ingen vurdering"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Dette programmet er vurdert som <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Inngang støtter ikke auto-kanalsøk"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Kunne ikke starte automatisk skanning for «<xliff:g id="TV_INPUT">%s</xliff:g>»"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d kanal er lagt til</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Ingen kanaler er lagt til"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Foreldrekontroll"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"På"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Av"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Andre land"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ingen"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ingen"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Ingen vurdering"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokkér program uten vurdering"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ingen"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Høye begrensninger"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Medium begrensninger"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Skriv inn PIN-koden din for å se på denne kanalen"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Skriv inn PIN-koden din for å se på dette programmet"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Dette programmet er vurdert som <xliff:g id="RATING">%1$s</xliff:g>. Skriv inn PIN-koden din for å se dette programmet"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Dette programmet har ingen vurdering. Skriv inn PIN-koden din for å se dette programmet"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Skriv inn PIN-koden din"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"For å konfigurere foreldrekontroll, angi en PIN-kode"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Skriv inn en ny PIN-kode"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Prøv på nytt, PIN-koden er feil."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Prøv på nytt, PIN-koden er feil"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Skriv inn postnummeret ditt."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Direkte-TV-appen bruker postnummeret til å oppgi en fullstendig programoversikt for TV-kanalene."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Skriv inn postnummeret ditt"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Ugyldig postnummer"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Innstillinger"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Tilpass kanallisten"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Velg kanaler for programoversikten din"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanalkilder"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nye kanaler er tilgjengelig"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Foreldrekontroll"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Tidsforskyvning"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Ta opp mens du ser på direktesendte programmer, så du kan sette dem på pause eller spole bakover.\nAdvarsel: Dette kan redusere levetiden til den interne lagringen på grunn av intensiv bruk av lagringen."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Lisenser for åpen kildekode"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Åpen kildekode-lisenser"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Send tilbakemelding"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versjon"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"For å se på denne kanalen, trykk til høyre og skriv inn PIN-koden din"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"For å se på dette programmet, trykk til høyre og skriv inn PIN-koden din"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Dette programmet har ingen vurdering.\nFor å se dette programmet, trykk på knappen til høyre og skriv inn PIN-koden din"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Dette programmet har vurderingen <xliff:g id="RATING">%1$s</xliff:g>.\nFor å se på dette programmet, trykk til høyre og skriv inn PIN-koden din."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"For å se på denne kanalen, bruk Live TV-appen som er angitt som standard."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"For å se dette programmet, bruk Live TV-appen som er angitt som standard."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Dette programmet har ingen vurdering.\nFor å se dette programmet, bruk Live TV-appen som er angitt som standard."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Dette programmet er vurdert som <xliff:g id="RATING">%1$s</xliff:g>.\nFor å se dette programmet, bruk Live TV-appen som er angitt som standard."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programmet er blokkert"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Dette programmet har ingen vurdering"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Dette programmet er vurdert som <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Bare lyd"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Svakt signal"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Trykk på «SELECT» (VELG)"</b>" for å åpne TV-menyen."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Kunne ikke finne noen TV-inngang"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Kunne ikke finne TV-inngangen"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP støttes ikke"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Det finnes ingen tilgjengelige inndata som kan vises med PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tuner-typen kan ikke brukes. Kjør Live TV-appen med tuner-typen for TV-inndata."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Justering mislyktes."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Kunne ikke finne noen app som kan håndtere denne handlingen."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d planlagte opptak</item>
       <item quantity="one">%1$d planlagt opptak</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Avbryt opptak"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Stopp opptak"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Se på"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Spill av fra begynnelsen"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Gjenoppta avspilling"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Når det er for mange programmer som skal tas opp samtidig, blir bare programmene med høyere prioritet tatt opp."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Lagre"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Engangsopptak har høyeste prioritet"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Avbryt"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Avbryt"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Glem"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stopp"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Se tidsplanen for opptak"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Bare dette programmet"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Spill inn dette i stedet"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Kanseller dette opptaket"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Se nå"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Slett opptak …"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Opptaksbar"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Opptak planlagt"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Opptakskonflikt"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Tar opp"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Opptaket mislyktes"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Leser av programmer for å opprette tidsplaner for opptak"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Leser av programmer"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Leser av programmer"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Se nylige opptak"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Opptaket av <xliff:g id="PROGRAMNAME">%1$s</xliff:g> er ufullstendig."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Opptakene av <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> og <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> er ufullstendige."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Opptakene av <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> og <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> er ufullstendige."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Opptaket av <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ble ikke fullført på grunn av utilstrekkelig lagringsplass."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Opptakene av <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> og <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ble ikke fullført på grunn av utilstrekkelig lagringsplass."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Opptakene av <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> og <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ble ikke fullført på grunn av utilstrekkelig lagringsplass."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR trenger mer lagringsplass"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Det kommer til å være mulig til å ta opp programmer med DVR. Det er imidlertid ikke nok lagringsplass på enheten din til at DVR kan fungere. Koble til en ekstern stasjon på <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB eller mer, og følg trinnene for å formatere den som lagringsenhet."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Det kommer til å være mulig til å ta opp programmer med DVR. Det er imidlertid ikke nok lagringsplass på enheten din til at DVR kan fungere. Koble til en ekstern stasjon på <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB eller mer, og følg trinnene for å formatere den som lagringsenhet."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Ikke nok lagringsplass"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Dette programmet blir ikke tatt opp fordi det ikke er nok lagringsplass. Prøv å slette noen eksisterende opptak."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Manglende lagringsplass"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Noe av lagringsplassen som brukes av DVR, mangler. Koble til den eksterne disken du bruke tidligere, for å slå på DVR igjen. Eventuelt kan du velge å glemme lagringsplassen hvis den ikke er tilgjengelig lenger."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Vil du glemme lagring?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Alt innspilt innhold og alle tidsplanene går tapt."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Vil du stoppe opptaket?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Det innspilte innholdet blir lagret."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Opptaket av <xliff:g id="PROGRAMNAME">%1$s</xliff:g> stoppes fordi det har konflikter med dette programmet. Det innspilte innholdet blir lagret."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Opptak er planlagt, men har konflikter"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Opptak har startet, men har konflikter"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> blir tatt opp."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Det samme programmet er allerede planlagt for opptak <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Allerede tatt opp"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Dette programmet er allerede tatt opp. Det er tilgjengelig i DVR-biblioteket."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Opptak av serie er planlagt"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> av dem blir ikke tatt opp på grunn av konflikter.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Det blir ikke tatt opp på grunn av konflikter.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episoder av denne serien og andre serier blir ikke tatt opp på grunn av konflikter.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episoder av denne serien og andre serier blir ikke tatt opp på grunn av konflikter.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Én episode av andre serier blir ikke tatt opp på grunn av konflikter.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Én episode av andre serier blir ikke tatt opp på grunn av konflikter.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episoder av andre serier blir ikke tatt opp på grunn av konflikter.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opptak er planlagt for <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episoder av andre serier blir ikke tatt opp på grunn av konflikter.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Finner ikke programopptaket."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Relaterte opptak"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Ingen programbeskrivelse)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d opptak</item>
       <item quantity="one">%1$d opptak</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Vil du stoppe opptaket av serien?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Episoder som er tatt opp, er fremdeles tilgjengelige i DVR-biblioteket."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stopp"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Ingen episoder er på luften nå."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Ingen episoder er tilgjengelige.\nDe blir tatt opp når de er tilgjengelige."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minutter)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> i dag"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> i morgen"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Poengsum"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programmer som er tatt opp"</string>
 </resources>
diff --git a/res/values-ne-v23/strings.xml b/res/values-ne-rNP-v23/strings.xml
similarity index 100%
rename from res/values-ne-v23/strings.xml
rename to res/values-ne-rNP-v23/strings.xml
diff --git a/res/values-ne/arrays.xml b/res/values-ne-rNP/arrays.xml
similarity index 100%
rename from res/values-ne/arrays.xml
rename to res/values-ne-rNP/arrays.xml
diff --git a/res/values-ne/rating_system_strings.xml b/res/values-ne-rNP/rating_system_strings.xml
similarity index 100%
rename from res/values-ne/rating_system_strings.xml
rename to res/values-ne-rNP/rating_system_strings.xml
diff --git a/res/values-ne/strings.xml b/res/values-ne-rNP/strings.xml
similarity index 76%
rename from res/values-ne/strings.xml
rename to res/values-ne-rNP/strings.xml
index 142dfad..9bc3dca 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"मोनो"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"स्टेरियो"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"प्ले नियन्त्रणहरु"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"भर्खरैका च्यानलहरू"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"च्यानलहरू"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"टिभी विकल्पहरू"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP विकल्पहरू"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"यस च्यानलका लागि प्ले नियन्त्रणहरू अनुपलब्ध"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"प्ले वा पज"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"फास्ट फर्वार्ड"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"बन्द क्याप्सनहरु"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"डिस्प्ले मोड"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"खुला"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"बन्द"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"मल्टि-अडियो"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"अझ बढी च्यानलहरू प्राप्त गर्नुहोस्"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"सेटिङहरू"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"स्रोत"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"स्वाप"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"खुला"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"बन्द"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"आवाज"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"मुख्य"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP सन्झ्याल"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"लेआउट"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"तल्लो दायाँ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"माथिल्लो दायाँ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"माथिल्लो बायाँ"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"तल्लो बायाँ"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"सँगसँगै"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"आकार"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"ठूलो"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"सानो"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"इनपुट स्रोत"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"टिभी (एन्टेना/केबल)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"कुनै पनि कार्यक्रम जानकारी छैन"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"केही सूचना छैन"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"अवरुद्ध च्यानल"</string>
-    <string name="default_language" msgid="4122326459624337928">"अज्ञात भाषा"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"अज्ञात भाषा"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"उपशीर्षकहरू %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"उपशीर्षक"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"बन्द गर्नुहोस्"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"फर्‍म्याटिङ अनुकूलित"</string>
@@ -73,7 +54,7 @@
     <string name="multi_audio_channel_surround_6" msgid="6066304966228963942">"५.१ सराउन्ड"</string>
     <string name="multi_audio_channel_surround_8" msgid="2765140653768694313">"७.१ सराउन्ड"</string>
     <string name="multi_audio_channel_suffix" msgid="4443825738196093772">"%d च्यानलहरु"</string>
-    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"च्यानल सूची अनुकूलन गर्नुहोस्"</string>
+    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"च्यानल सूची आफू अनुकूल गर्नुहोस्"</string>
     <string name="edit_channels_item_select_group" msgid="4953000352257999703">"समूह छान्नुहोस्"</string>
     <string name="edit_channels_item_deselect_group" msgid="5092649099546997807">"समूह अचयन नगर्नुहोस्"</string>
     <string name="edit_channels_item_group_by" msgid="7794571851966798199">"द्वारा समूह"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"द्वारा समूह"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"यो कार्यक्रम निषेध गरिएको छ।"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"यो कार्यक्रमको मूल्याङ्कन गरिएको छैन"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"यो कार्यक्रम मूल्याङ्कन <xliff:g id="RATING">%1$s</xliff:g> गरिएको छ"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"इनपुटले स्वतः स्क्यान समर्थन गर्दैन"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' का लागि स्वतः स्क्यान सुरु गर्न असमर्थ"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d च्यानल थपियो</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"कुनै पनि च्यानल थपिएन"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ट्यूनर"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"मुख्य नियन्त्रणहरू"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"खोल्नुहोस्"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"बन्द गर्नुहोस्"</string>
@@ -108,11 +89,13 @@
     <string name="other_countries" msgid="8342216398676184749">"अन्य देशहरू"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"कुनै पनि होइन"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"कुनै पनि होइन"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"मूल्याङ्कन नगरिएको"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"मूल्याङ्कन नगरिएका कार्यक्रमहरूमाथि रोक लगाउनु"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"कुनै पनि होइन"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"उच्च प्रतिबन्धहरू"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"मध्यम प्रतिबन्धहरू"</string>
     <string name="option_rating_low" msgid="5800146024503377969">"न्यून प्रतिबन्धहरू"</string>
-    <string name="option_rating_custom" msgid="3155377834510646436">"अनुकूलन"</string>
+    <string name="option_rating_custom" msgid="3155377834510646436">"आफू अनुकूल"</string>
     <string name="option_rating_high_description" msgid="609567565273278745">"बालबालिकाका लागि उपयुक्त सामग्री"</string>
     <string name="option_rating_medium_description" msgid="7169199016608935280">"ठूला बच्चाहरुका लागि उपयुक्त सामग्री"</string>
     <string name="option_rating_low_description" msgid="4740109576615335045">"किशोर किशोरीहरुका लागि उपयुक्त सामग्री"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"यो च्यानल हेर्न तपाईँको PIN प्रविष्टि गर्नुहोस्"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"यो कार्यक्रम हेर्न तपाईँको PIN प्रविष्टि गर्नुहोस्"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"यस कार्यक्रमलाई <xliff:g id="RATING">%1$s</xliff:g> भनेर मूल्याङ्कन गरिएको छ। यो कार्यक्रम हेर्न आफ्नो PIN प्रविष्ट गर्नुहोस्"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"यो कार्यक्रमको मूल्याङ्कन गरिएको छैन। यो कार्यक्रम हेर्न आफ्नो PIN प्रविष्ट गर्नुहोस्"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"आफ्नो पिन प्रविष्ट गर्नुहोस्"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"अभिभावकत्वको नियन्त्रण सेट गर्न, एउटा PIN सिर्जना गर्नुहोस्"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"नयाँ PIN प्रविष्टि गर्नुहोस्"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"त्यो PIN गलत थियो। पुनः प्रयास गर्नुहोस्।"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"पुनः प्रयास गर्नुहोस्, PIN मेल खाँदैन"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"आफ्नो जिप कोड प्रविष्ट गर्नुहोस्।"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"TV च्यानलहरूको कार्यक्रमको बारेमा समग्र मार्गदर्शन प्रदान गर्न लाइभ च्यानल अनुप्रयोगले उक्त जिप कोड प्रयोग गर्नेछ।"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"आफ्नो जिप कोड प्रविष्ट गर्नुहोस्"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"अमान्य ZIP कोड"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"सेटिङहरू"</string>
-    <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"च्यानलको सूची अनुकूलन गर्नुहोस्"</string>
+    <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"च्यानलको सूची आफू अनुकूल गर्नुहोस्"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"आफ्नो कार्यक्रम निर्देशिकाको लागि च्यानलहरू छनौट गर्नुहोस्"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"च्यानलका स्रोतहरू"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"नयाँ च्यानलहरू उपलब्ध छन्"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"अभिभावकीय नियन्त्रणहरू"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"टाइमसिफ्ट"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"तपाईंले लाइभ कार्यक्रमहरूलाई पज वा रिवाइन्ड गर्न सक्नुहोस् भन्नका खातिर हेर्दाहेर्दै रेकर्ड गर्नुहोस्।\nचेतावनी: यसले भण्डारणको अत्यन्त धेरै प्रयोग गरेर आन्तरिक भण्डारणको आयु कम गर्न सक्छ।"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"स्रोतका इजाजतपत्रहरू खोल्नुहोस्"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"खुला स्रोत इजाजतपत्रहरू"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"प्रतिक्रिया पठाउनुहोस्"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"संस्करण"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"यो च्यानल हेर्न, दायाँ प्रेस गर्नुहोस् र आफ्नो पिन प्रविष्ट गर्नुहोस्"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"यो कार्यक्रम हेर्न, दायाँ प्रेस गर्नुहोस् र आफ्नो पिन प्रविष्ट गर्नुहोस्"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"यो कार्यक्रमको मूल्याङ्कन गरिएको छैन।\nयो कार्यक्रम हेर्न दायाँ थिचेर आफ्नो PIN प्रविष्ट गर्नुहोस्"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"यो कार्यक्रम मूल्याङ्कन <xliff:g id="RATING">%1$s</xliff:g> गरिएको छ।\nयो कार्यक्रम हेर्न, दायाँ थिच्नुहोस् र आफ्नो PIN प्रविष्ट गर्नुहोस्।"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"यो च्यानल हेर्न, पूर्वनिर्धारित लाइभ TV अनुप्रयोग प्रयोग गर्नुहोस्।"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"यो कार्यक्रम हेर्न, पूर्वनिर्धारित लाइभ TV अनुप्रयोगको प्रयोग गर्नुहोस्।"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"यो कार्यक्रमको मूल्याङ्कन गरिएको छैन।\nयो कार्यक्रम हेर्न पूर्वनिर्धारित लाइभ TV अनुप्रयोग प्रयोग गर्नुहोस्।"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"यो कार्यक्रम मूल्याङ्कन गरिएको छ <xliff:g id="RATING">%1$s</xliff:g>।\n यो कार्यक्रम हेर्न, पूर्वनिर्धारित लाइभ TV अनुप्रयोग प्रयोग गर्नुहोस्।"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"प्रोग्राम ब्लक गरिएको छ"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"यो कार्यक्रमको मूल्याङ्कन गरिएको छैन"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"यो कार्यक्रम मूल्याङ्कन <xliff:g id="RATING">%1$s</xliff:g> गरिएको छ"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"अडियो मात्र"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"सिग्नल कमजोर छ"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"टिभी मेनु खोल्न "<b>"SELECT थिच्नुहोस्"</b>"।"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"कुनै पनि टिभी स्रोत भेटिएन।"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"टिभी स्रोत भेटिएन लागेन"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP समर्थित छैन"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP सँग देखाउन सकिने कुनै स्रोत उपलब्ध छैन।"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ट्यूनर प्रकार अनुपयुक्त। कृपया ट्यूनर प्रकार टिभी स्रोतको लागि Live TV को अनुप्रयोग सुरु गर्नुहोस।"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ट्युन गर्न असफल"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"यो कार्य सम्हाल्न कुनै पनि अनुप्रयोग भेटिएन।"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d रेकर्डिङहरूको समय निर्धारण गरियो</item>
       <item quantity="one">%1$d रेकर्डिङको समय निर्धारण गरियो</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"रेकर्डिङलाई रद्द गर्नुहोस्"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"रेकर्डिङलाई रोक्नुहोस्"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"हेर्नुहोस्"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"सुरुबाट चलाउनुहोस्"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"पुनःसुरु गर्नुहोस्"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"एकै समयमा अत्यन्त धेरै कार्यक्रमहरू रेकर्ड गर्नुपर्ने भएकाले उच्च प्राथमिकता भएका कार्यक्रमहरूलाई मात्र रेकर्ड गरिनेछ।"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"सुरक्षित गर्नुहोस्"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"एक-पटके रेकर्डिङहरूलाई सबैभन्दा उच्च प्राथमिकता दिइन्छ"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"रद्द गर्नु"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"रद्द गर्नुहोस्"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"बिर्सनुहोस्"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"रोक्नुहोस्"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"रेकर्डिङको समयतालिका हेर्नुहोस्"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"यो कार्यक्रम मात्र"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"बरु यो रेकर्ड गर्नुहोस्"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"यस रेकर्डिङलाई रद्द गर्नुहोस्"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"अहिले हेर्नुहोस्"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"रेकर्डिङहरू मेट्नुहोस्…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"रेकर्ड गर्न मिल्ने"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"रेकर्डिङको कार्यतालिका निर्धारण गरिएको छ"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"रेकर्डिङ सम्बन्धी असहमति"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"रेकर्ड गर्दै"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"रेकर्डिङ गर्न सकिएन"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"रेकर्डिङका समय तालिकाहरू सिर्जना गर्न कार्यक्रमहरू पढ्दै"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"कार्यक्रमहरूको जानकारी पढ्दै"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"कार्यक्रमहरूको जानकारी पढ्दै"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"हालका रेकर्डिङहरू हेर्नुहोस्"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> को रेकर्डिङ अपूर्ण छ।"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> र <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> का रेकर्डिङहरू अपूर्ण छन्।"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> र <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> का रेकर्डिङहरू अपूर्ण छन्।"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"भण्डारण स्थान अपर्याप्त भएकाले <xliff:g id="PROGRAMNAME">%1$s</xliff:g> को रेकर्डिङ पूरा भएन।"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"भण्डारण स्थान अपर्याप्त भएकाले <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> र <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> का रेकर्डिङहरू पूरा भएनन्।"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"भण्डारण स्थान अपर्याप्त भएकाले <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> र <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> का रेकर्डिङहरू पूरा भएनन्।"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR लाई थप भण्डारण चाहिन्छ"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"तपाईँले DVR मार्फत कार्यक्रमहरू रेकर्ड गर्न सक्नुहुनेछ। यद्यपि, अहिले तपाईँको यन्त्रमा DVR ले काम गर्न पुग्ने गरी पर्याप्त भण्डारण छैन। कृपया <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> जि.बि.वा सो भन्दा बढी भण्डारण क्षमता भएको कुनै बाह्य ड्राइभ जडान गर्नुहोस् र त्यसलाई यन्त्रको भण्डारणका रूपमा फर्म्याट गर्न आवश्यक कदमहरू चाल्नुहोस्।"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"तपाईँले DVR मार्फत कार्यक्रमहरू रेकर्ड गर्न सक्नुहुनेछ। यद्यपि, अहिले तपाईँको यन्त्रमा DVR ले काम गर्न पुग्ने गरी पर्याप्त भण्डारण छैन। कृपया <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> जि.बि.वा सो भन्दा बढी भण्डारण क्षमता भएको कुनै बाह्य ड्राइभ जडान गर्नुहोस् र त्यसलाई यन्त्रको भण्डारणका रूपमा फर्म्याट गर्न आवश्यक कदमहरू चाल्नुहोस्।"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"पर्याप्त भण्डारण छैन"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"पर्याप्त भण्डारण उपलब्ध नभएको हुनाले यस कार्यक्रमलाई रेकर्ड गरिने छैन। केही विद्यमान रेकर्डिङहरू मेटाई हेर्नुहोस्।"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"भण्डारण उपलब्ध छैन"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR ले प्रयोग गरेको केही भण्डारण उपलब्ध छैन। DVR लाई पुन: सक्षम पार्न कृपया तपाईँले पहिले प्रयोग गर्नुभएको बाह्य ड्राइभलाई जडान गर्नुहोस्। वैकल्पिक रूपमा, यदि अब भण्डारण उपलब्ध छैन भने तपाईँ त्यसलाई बिर्सने विकल्प छान्न सक्नुहुन्छ।"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"भण्डारण बिर्सने हो?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"तपाईँका रेकर्ड गरिएका सबै सामग्री र समय सहितका कार्यतालिकाहरू हराउने छन्।"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"रेकर्डिङ रोक्ने हो?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"रेकर्ड गरिएको सामग्रीलाई सुरक्षित गरिनेछ।"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"यस कार्यक्रमसँग परस्पर विरोधी भएकाले <xliff:g id="PROGRAMNAME">%1$s</xliff:g> को रेकर्डिङ रोकिने छ। रेकर्ड गरिएका सामग्रीहरू सुरक्षित गरिने छन्।"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"रेकर्डिङको कार्यतालिका निर्धारण गरिएको छ तर यसमा असहमतिहरू छन्"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"रेकर्डिङ सुरु भएको छ तर यसमा असहमतिहरू छन्"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> लाई रेकर्ड गरिनेछ।"</string>
@@ -300,23 +293,35 @@
       <item quantity="other"><xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> र थप %3$d कार्यक्रमहरूलाई रेकर्ड गरिने छैन।</item>
       <item quantity="one"><xliff:g id="CONFLICTPROGRAMNAME_1_0">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_1">%2$s</xliff:g> र थप %3$d कार्यक्रमलाई रेकर्ड गरिने छैन।</item>
     </plurals>
-    <string name="dvr_schedule_dialog_title" msgid="5235629824986156058">"तपाईँ के रेकर्ड गर्न चाहनुहुन्छ?"</string>
-    <string name="dvr_channel_record_duration_dialog_title" msgid="4601361040431047918">"तपाईँ कति बेरसम्म रेकर्ड गर्न चाहनुहुन्छ?"</string>
+    <string name="dvr_schedule_dialog_title" msgid="5235629824986156058">"तपाईं के रेकर्ड गर्न चाहनुहुन्छ?"</string>
+    <string name="dvr_channel_record_duration_dialog_title" msgid="4601361040431047918">"तपाईं कति बेरसम्म रेकर्ड गर्न चाहनुहुन्छ?"</string>
     <string name="dvr_already_scheduled_dialog_title" msgid="4525318291210934311">"पहिले नै समय सहितको कार्यतालिका निर्धारण गरिएको छ"</string>
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"यस कार्यक्रमलाई पहिले नै <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> मा रेकर्ड गर्न समय सहितको कार्यतालिका निर्धारण गरिएको छ।"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"पहिले नै रेकर्ड गरिएको छ"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"यस कार्यक्रमलाई पहिले नै रेकर्ड गरिएको छ। यो DVR को लाइब्रेरीमा उपलब्ध छ।"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"शृङ्खलाहरूको रेकर्डिङको समय तालिका बनाइयो"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> का <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकर्डिङहरूको समय तालिका तय गरिएको छ।</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> को <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> रेकर्डिङको समय तालिका तय गरिएको छ।</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> का <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकर्डिङहरूको समय तालिका तय गरिएको छ। तालमेल नमिलेका कारण ती मध्ये <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> लाई रेकर्ड गरिने छैन।</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> को <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> रेकर्डिङको समय तालिका तय गरिएको छ। तालमेल नमिलेका कारण यसलाई रेकर्ड गरिने छैन।</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> का <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रेकर्डिङहरूको समय तालिका तय गरिएको छ। तालमेल नमिलेका कारण यस शृङ्खला र अन्य शृङ्खलाका <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> एपिसोडहरूलाई रेकर्ड गरिने छैन।</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> को <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> रेकर्डिङको समय तालिका तय गरिएको छ। तालमेल नमिलेका कारण यस शृङ्खला र अन्य शृङ्खलाका <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> एपिसोडहरूलाई रेकर्ड गरिने छैन।</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> का <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> रेकर्डिङहरूको समय तालिका तय गरिएको छ। तालमेल नमिलेका कारण अन्य शृङ्खलाको १ एपिसोडलाई रेकर्ड गरिने छैन।</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> को <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> रेकर्डिङको समय तालिका तय गरिएको छ। तालमेल नमिलेका कारण अन्य शृङ्खलाको १ एपिसोडलाई रेकर्ड गरिने छैन।</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> का <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> रेकर्डिङहरूको समय तालिका तय गरिएको छ। तालमेल नमिलेका कारण अन्य शृङ्खलाका <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> एपिसोडहरूलाई रेकर्ड गरिने छैन।</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> को <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> रेकर्डिङको समय तालिका तय गरिएको छ। तालमेल नमिलेका कारण अन्य शृङ्खलाका <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> एपिसोडहरूलाई रेकर्ड गरिने छैन।</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"रेकर्ड गरिएको कार्यक्रम भेट्टिएन।"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"सम्बन्धित रेकर्डिङहरू"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(कार्यक्रम सम्बन्धी वर्णन छैन)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d रेकर्डिङ</item>
       <item quantity="one">%1$d रेकर्डिङ</item>
@@ -325,7 +330,7 @@
     <string name="dvr_schedules_deletion_info" msgid="2837586459900271031">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> लाई रेकर्डिङको समय सहितको कार्यतालिकाबाट हटाइयो"</string>
     <string name="dvr_schedules_tuner_conflict_will_be_partially_recorded" msgid="5280490298546908729">"ट्युनर सम्बन्धी असहमतिका कारण आंशिक रूपमा रेकर्ड गरिनेछ।"</string>
     <string name="dvr_schedules_tuner_conflict_will_not_be_recorded_info" msgid="5065400564003201095">"ट्युनर सम्बन्धी असहमतिका कारण रेकर्ड गरिने छैन।"</string>
-    <string name="dvr_schedules_empty_state" msgid="1291529283469462741">"अहिलेसम्म समय सहितको कार्यतालिका निर्धारण गरिएको कुनै रेकर्डिङ छैन।\nतपाईँ कार्यक्रम निर्देशिका मार्फत रेकर्डिङको समय सहितको कार्यतालिका निर्धारण गर्न सक्नुहुन्छ।"</string>
+    <string name="dvr_schedules_empty_state" msgid="1291529283469462741">"अहिलेसम्म समय सहितको कार्यतालिका निर्धारण गरिएको कुनै रेकर्डिङ छैन।\nतपाईं कार्यक्रम निर्देशिका मार्फत रेकर्डिङको समय सहितको कार्यतालिका निर्धारण गर्न सक्नुहुन्छ।"</string>
     <plurals name="dvr_series_schedules_header_description" formatted="false" msgid="9077188267856194114">
       <item quantity="other">रेकर्डिङ सम्बन्धी %1$d असहमतिहरू</item>
       <item quantity="one">रेकर्डिङ सम्बन्धी %1$d असहमति</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"शृंखलाको रेकर्डिङ रोक्ने हो?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"रेकर्ड गरिएका एपिसोडहरू DVR सम्बन्धी लाइब्रेरीमा उपलब्ध रहनेछन्।"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"रोक्नुहोस्"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"अहिले कुनै एपिसोड प्रसारण भइरहेको छैन।"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"कुनै एपिसोड उपलब्ध छैन।\nएपिसोडहरू उपलब्ध भएपछि तिनीहरूलाई रेकर्ड गरिनेछ।"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d मिनेट)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"आज <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"भोलि <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"अङ्क"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"रेकर्ड गरिएका कार्यक्रमहरू"</string>
 </resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index f24ed1c..a3e9dfe 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Afspeelknoppen"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Recente kanalen"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanalen"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Tv-opties"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-opties"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Er zijn geen afspeelknoppen beschikbaar voor dit kanaal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Afspelen of onderbreken"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Vooruitspoelen"</string>
@@ -32,36 +31,18 @@
     <string name="channels_item_program_guide" msgid="2889807207930678418">"Programmagids"</string>
     <string name="channels_item_setup" msgid="6557412175737379022">"Nieuwe kanalen beschikbaar"</string>
     <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"<xliff:g id="APP_NAME">%1$s</xliff:g> openen"</string>
-    <string name="options_item_closed_caption" msgid="5945274655046367170">"Ondertiteling"</string>
+    <string name="options_item_closed_caption" msgid="5945274655046367170">"Ondertitels"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Weergavemodus"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Aan"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Uit"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Kanalen ophalen"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Instellingen"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Bron"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Wisselen"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Aan"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Uit"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Geluid"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Hoofd"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-venster"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Lay-out"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Rechtsonder"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Rechtsboven"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Linksboven"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Linksonder"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Naast elkaar"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Formaat"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Groot"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Klein"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Invoerbron"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Tv (antenne/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Geen programmagegevens"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Geen informatie"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Geblokkeerd kanaal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Onbekende taal"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Onbekende taal"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Ondertiteling %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Ondertiteling"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Uit"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Opmaak aanpassen"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Groeperen op"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Dit programma is geblokkeerd"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Dit programma is niet geclassificeerd"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Dit programma is beoordeeld als <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"De invoer biedt geen ondersteuning voor automatisch scannen"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Kan automatisch zoeken naar \'<xliff:g id="TV_INPUT">%s</xliff:g>\' niet starten"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d kanaal toegevoegd</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Geen kanalen toegevoegd"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Ouderlijk toezicht"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Aan"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Uit"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Andere landen"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Geen"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Geen"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Niet geclassificeerd"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Niet-geclas. prog. blokkeren"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Geen"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Strenge beperkingen"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Gem. beperkingen"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Je pincode opgeven om dit kanaal te bekijken"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Je pincode opgeven om dit programma te bekijken"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Dit programma heeft de classificatie <xliff:g id="RATING">%1$s</xliff:g>. Geef je pincode op om dit programma te bekijken."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Dit programma is niet geclassificeerd. Geef je pincode op om dit programma te bekijken."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Je pincode opgeven"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Stel een pincode in om ouderlijk toezicht in te stellen"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Nieuwe pincode opgeven"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Die pincode is onjuist. Probeer het opnieuw."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Probeer het opnieuw; de pincode komt niet overeen"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Je postcode opgeven"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"De app Live tv gebruikt je postcode om een volledige programmagids voor de tv-kanalen aan te leveren."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Geef je postcode op"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Ongeldige postcode"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Instellingen"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Kanaallijst aanpassen"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Kanalen kiezen voor je tv-gids"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanaalbronnen"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Nieuwe kanalen beschikbaar"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Ouderlijk toezicht"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Tijdverschuiving"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Neem op tijdens het kijken zodat je live programma\'s kunt onderbreken of terugspoelen.\nWaarschuwing: De levensduur van de interne opslag kan afnemen door het intensieve gebruik."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Open-sourcelicenties"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Open-sourcelicenties"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Feedback verzenden"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versie"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Als je dit kanaal wilt bekijken, druk je rechts en geef je je pincode op"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Als je dit programma wilt bekijken, druk je rechts en geef je je pincode op"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Dit programma is niet geclassificeerd.\nAls je dit programma wilt bekijken, druk je op Rechts en geef je je pincode op."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Dit programma is beoordeeld als <xliff:g id="RATING">%1$s</xliff:g>.\nAls je dit programma wilt bekijken, druk je rechts en geef je je pincode op."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Gebruik de standaardapp voor live tv om dit kanaal te bekijken."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Gebruik de standaardapp voor live tv om dit programma te bekijken."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Dit programma is niet geclassificeerd.\nAls je dit programma wilt bekijken, gebruik je de standaard-app voor live tv."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Dit programma heeft de classificatie <xliff:g id="RATING">%1$s</xliff:g>.\nGebruik de standaardapp voor live tv om dit programma te bekijken."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programma is geblokkeerd"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Dit programma is niet geclassificeerd"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Dit programma is beoordeeld als <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Alleen audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Zwak signaal"</string>
@@ -181,15 +174,13 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Druk op SELECTEREN"</b>" voor toegang tot het tv-menu."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Geen tv-invoer gevonden"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Kan de tv-invoer niet vinden"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP wordt niet ondersteund"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Geen beschikbare invoer die kan worden weergegeven met PIP"</string>
-    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tunertype is geen geschikte optie. Start de app Live kanalen voor tv-invoer van het type tuner."</string>
+    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tunertype is geen geschikte optie. Start de Live tv-app voor tv-invoer van het type tuner."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Afstemmen mislukt"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Er is geen app gevonden om deze actie uit te voeren."</string>
     <string name="msg_all_channels_hidden" msgid="777397634062471936">"Alle bronkanalen zijn verborgen.\nSelecteer ten minste één kanaal om te bekijken."</string>
     <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"De video is onverwacht niet beschikbaar"</string>
     <string name="msg_back_key_guide" msgid="7404682718828721924">"De toets TERUG is voor verbonden apparaten. Druk op de knop HOME om te sluiten."</string>
-    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"De app \'Live kanalen\' heeft toestemming nodig om tv-vermeldingen te lezen."</string>
+    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"De app \'Live tv\' heeft toestemming nodig om tv-vermeldingen te lezen."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Je bronnen configureren"</string>
     <string name="setup_sources_description" msgid="5695518946225445202">"Live tv combineert de functionaliteit van traditionele tv-kanalen met streaming kanalen die worden geleverd door apps. \n\nJe kunt aan de slag gaan door de kanaalbronnen te configureren die al zijn geïnstalleerd. Of browse in de Google Play Store voor meer apps die live tv aanbieden."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Opnamen en planningen"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d opnamen gepland</item>
       <item quantity="one">%1$d opname gepland</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Opname annuleren"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Opname stoppen"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Bekijken"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Afspelen vanaf het begin"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Afspelen hervatten"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Wanneer er te veel programma\'s tegelijk moeten worden opgenomen, worden alleen de programma\'s met de hogere prioriteit opgenomen."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Opslaan"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Eenmalige opnamen krijgen de hoogste prioriteit"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Annuleren"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Annuleren"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Vergeten"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stoppen"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Opnameschema bekijken"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Dit afzonderlijke programma"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Dit programma opnemen"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Deze opname annuleren"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Nu bekijken"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Opnamen verwijderen"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Kan worden opgenomen"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Opname gepland"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Opnameconflict"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Opnemen"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Opname mislukt"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Programma\'s lezen om opnameplanningen te maken"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Programma\'s lezen"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Programma\'s lezen"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Recente opnamen bekijken"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"De opname van <xliff:g id="PROGRAMNAME">%1$s</xliff:g> is niet voltooid."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"De opnamen van <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> en <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> zijn niet voltooid."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"De opnamen van <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> en <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> zijn niet voltooid."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"De opname van <xliff:g id="PROGRAMNAME">%1$s</xliff:g> is niet voltooid vanwege onvoldoende opslagruimte."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"De opnamen van <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> en <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> zijn niet voltooid vanwege onvoldoende opslagruimte."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"De opnamen van <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> en <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> zijn niet voltooid vanwege onvoldoende opslagruimte."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Voor DVR is meer opslagruimte nodig"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Je kunt programma\'s opnemen met DVR. Er is echter momenteel onvoldoende opslagruimte beschikbaar op je apparaat om DVR te gebruiken. Sluit een externe schijf aan die <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB of groter is en volg de stappen om deze te formatteren als apparaatopslag."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Je kunt programma\'s opnemen met DVR. Er is echter momenteel onvoldoende opslagruimte beschikbaar op je apparaat om DVR te gebruiken. Sluit een externe schijf aan die <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB of groter is en volg de stappen om deze te formatteren als apparaatopslag."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Onvoldoende opslagruimte"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Dit programma wordt niet opgenomen omdat er onvoldoende opslagruimte is. Verwijder een aantal bestaande opnamen."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Opslag ontbreekt"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Een deel van de opslagruimte ontbreekt die door de DVR wordt gebruikt. Sluit de externe schijf aan die je eerder hebt gebruikt om DVR opnieuw in te schakelen. Je kunt er ook voor kiezen de opslagruimte te vergeten als deze niet langer beschikbaar is."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Opslag vergeten?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Al je opgenomen content en planningen gaan verloren."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Opname stoppen?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"De opgenomen content wordt opgeslagen."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"De opname van <xliff:g id="PROGRAMNAME">%1$s</xliff:g> wordt gestopt omdat deze conflicteert met dit programma. De opgenomen content wordt opgeslagen."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Opname ingepland, maar heeft conflicten"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"De opname is gestart, maar heeft conflicten"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> wordt opgenomen."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Hetzelfde programma is al ingepland voor opname om <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Al opgenomen"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Dit programma is al opgenomen. Het is beschikbaar in de DVR-bibliotheek."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Serie-opname gepland"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">Er zijn <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opnamen gepland voor <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">Er is <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname gepland voor <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">Er zijn <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opnamen gepland voor <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> hiervan worden niet opgenomen vanwege conflicten.</item>
+      <item quantity="one">Er is <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname gepland voor <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Dit wordt niet opgenomen vanwege conflicten.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">Er zijn <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> opnamen gepland voor <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> afleveringen van deze serie en andere series worden niet opgenomen vanwege conflicten.</item>
+      <item quantity="one">Er is <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname gepland voor <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> afleveringen van deze serie en andere series worden niet opgenomen vanwege conflicten.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">Er zijn <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> opnamen gepland voor <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 aflevering van andere series wordt niet opgenomen vanwege conflicten.</item>
+      <item quantity="one">Er is <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname gepland voor <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 aflevering van andere series wordt niet opgenomen vanwege conflicten.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">Er zijn <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> opnamen gepland voor <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> afleveringen van andere series worden niet opgenomen vanwege conflicten.</item>
+      <item quantity="one">Er is <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> opname gepland voor <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> afleveringen van andere series worden niet opgenomen vanwege conflicten.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Opgenomen programma niet gevonden."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Gerelateerde opnamen"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Geen programmabeschrijving)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d opnamen</item>
       <item quantity="one">%1$d opname</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Serie-opname stoppen?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Opgenomen afleveringen blijven beschikbaar in de DVR-bibliotheek."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stoppen"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Er worden nu geen afleveringen uitgezonden."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Er zijn geen afleveringen beschikbaar.\nZe worden opgenomen zodra ze beschikbaar zijn."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minuten)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> vandaag"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> morgen"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Score"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Opgenomen programma\'s"</string>
 </resources>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
new file mode 100644
index 0000000..5415e3b
--- /dev/null
+++ b/res/values-pa-rIN/strings.xml
@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ 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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="audio_channel_mono" msgid="8812941280022167428">"ਮੋਨੋ"</string>
+    <string name="audio_channel_stereo" msgid="5798223286366598036">"ਸਟੀਰੀਓ"</string>
+    <string name="menu_title_play_controls" msgid="2490237359425190652">"ਪਲੇਬੈਕ ਕੰਟਰੋਲ"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ਚੈਨਲ"</string>
+    <string name="menu_title_options" msgid="7184594626814914022">"ਟੀਵੀ ਵਿਕਲਪ"</string>
+    <string name="play_controls_unavailable" msgid="8900698593131693148">"ਪਲੇਬੈਕ ਕੰਟਰੋਲ ਇਸ ਚੈਨਲ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
+    <string name="play_controls_description_play_pause" msgid="7225542861669250558">"ਚਲਾਓ ਜਾਂ ਰੋਕੋ"</string>
+    <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"ਤੇਜ਼ੀ ਨਾਲ ਅੱਗੇ ਕਰੋ"</string>
+    <string name="play_controls_description_fast_rewind" msgid="953488122681015803">"ਪਿੱਛੇ ਕਰੋ"</string>
+    <string name="play_controls_description_skip_next" msgid="1603587562124694592">"ਅੱਗੇ"</string>
+    <string name="play_controls_description_skip_previous" msgid="3858447678278021381">"ਪਿੱਛੇ"</string>
+    <string name="channels_item_program_guide" msgid="2889807207930678418">"ਪ੍ਰੋਗਰਾਮ ਗਾਈਡ"</string>
+    <string name="channels_item_setup" msgid="6557412175737379022">"ਨਵੇਂ ਚੈਨਲ ਉਪਲਬਧ ਹਨ"</string>
+    <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"<xliff:g id="APP_NAME">%1$s</xliff:g> ਨੂੰ ਖੋਲ੍ਹੋ"</string>
+    <string name="options_item_closed_caption" msgid="5945274655046367170">"ਬੰਦ ਸੁਰਖੀਆਂ"</string>
+    <string name="options_item_display_mode" msgid="7989243076748680140">"ਡਿਸਪਲੇ ਮੋਡ"</string>
+    <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
+    <string name="options_item_multi_audio" msgid="5118851311937896923">"ਮਲਟੀ-ਔਡੀਓ"</string>
+    <string name="options_item_more_channels" msgid="971040969622943300">"ਹੋਰ ਚੈਨਲ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+    <string name="options_item_settings" msgid="7623205838542400074">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ਟੀਵੀ (ਐਂਟੀਨਾ/ਕੇਬਲ)"</string>
+    <string name="no_program_information" msgid="1049844207745145132">"ਕੋਈ ਪ੍ਰੋਗਰਾਮ ਸਬੰਧੀ ਜਾਣਕਾਰੀ ਨਹੀਂ"</string>
+    <string name="program_title_for_no_information" msgid="384451471906070101">"ਕੋਈ ਜਾਣਕਾਰੀ ਨਹੀਂ"</string>
+    <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"ਬਲੌਕ ਕੀਤਾ ਚੈਨਲ"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"ਅਗਿਆਤ ਭਾਸ਼ਾ"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"ਬੰਦ ਸੁਰਖੀਆਂ %1$d"</string>
+    <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"ਬੰਦ ਸੁਰਖੀਆਂ"</string>
+    <string name="closed_caption_option_item_off" msgid="4824009036785647753">"ਬੰਦ"</string>
+    <string name="closed_caption_system_settings" msgid="1856974607743827178">"ਵੰਨਗੀਕਰਨ ਨੂੰ ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"ਬੰਦ ਸੁਰਖੀਆਂ ਦੇ ਲਈ ਸਿਸਟਮ-ਵਿਆਪਕ ਤਰਜੀਹਾਂ ਸੈੱਟ ਕਰੋ"</string>
+    <string name="side_panel_title_display_mode" msgid="6346286034015991229">"ਡਿਸਪਲੇ ਮੋਡ"</string>
+    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"ਮਲਟੀ-ਔਡੀਓ"</string>
+    <string name="multi_audio_channel_mono" msgid="6229173848963557723">"ਮੋਨੋ"</string>
+    <string name="multi_audio_channel_stereo" msgid="3758995659214256587">"ਸਟੀਰੀਓ"</string>
+    <string name="multi_audio_channel_surround_6" msgid="6066304966228963942">"5.1 ਸਰਾਊਂਡ"</string>
+    <string name="multi_audio_channel_surround_8" msgid="2765140653768694313">"7.1 ਸਰਾਊਂਡ"</string>
+    <string name="multi_audio_channel_suffix" msgid="4443825738196093772">"%d ਚੈਨਲ"</string>
+    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"ਚੈਨਲ ਸੂਚੀ ਨੂੰ ਵਿਸ਼ੇਸ਼ ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
+    <string name="edit_channels_item_select_group" msgid="4953000352257999703">"ਗਰੁੱਪ ਚੁਣੋ"</string>
+    <string name="edit_channels_item_deselect_group" msgid="5092649099546997807">"ਗਰੁੱਪ ਨੂੰ ਅਣਚੁਣਿਆ ਕਰੋ"</string>
+    <string name="edit_channels_item_group_by" msgid="7794571851966798199">"ਇਸ ਅਨੁਸਾਰ ਗਰੁੱਪ ਬਣਾਓ"</string>
+    <string name="edit_channels_group_by_sources" msgid="5481053601210461217">"ਚੈਨਲ ਸਰੋਤ"</string>
+    <string name="edit_channels_group_by_hd_sd" msgid="5582719665718278819">"HD/SD"</string>
+    <string name="edit_channels_group_divider_for_hd" msgid="5311355566660389423">"HD"</string>
+    <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
+    <string name="side_panel_title_group_by" msgid="1783176601425788939">"ਇਸ ਅਨੁਸਾਰ ਗਰੁੱਪ ਬਣਾਓ"</string>
+    <string name="program_guide_content_locked" msgid="198056836554559553">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਬਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਰੇਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+    <string name="program_guide_content_locked_format" msgid="514915272862967389">"ਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ <xliff:g id="RATING">%1$s</xliff:g> ਰੇਟ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+    <string name="msg_no_setup_activity" msgid="7746893144640239857">"ਇਨਪੁਟ ਸਵੈ-ਸਕੈਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ"</string>
+    <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' ਲਈ ਸਵੈ-ਸਕੈਨ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਦੇ ਅਯੋਗ"</string>
+    <string name="msg_unable_to_start_system_captioning_settings" msgid="705242616044165668">"ਬੰਦ ਸੁਰਖੀਆਂ ਲਈ ਸਿਸਟਮ-ਵਿਆਪਕ ਤਰਜੀਹਾਂ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਦੇ ਅਯੋਗ।"</string>
+    <plurals name="msg_channel_added" formatted="false" msgid="5301526166755938705">
+      <item quantity="one">%1$d ਚੈਨਲ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ</item>
+      <item quantity="other">%1$d ਚੈਨਲ ਸ਼ਾਮਲ ਕੀਤੇ ਗਏ</item>
+    </plurals>
+    <string name="msg_no_channel_added" msgid="2882586037409921925">"ਕੋਈ ਚੈਨਲ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੇ ਗਏ"</string>
+    <string name="menu_parental_controls" msgid="2474294054521345840">"ਮਾਪਿਆਂ ਦੇ ਕੰਟਰੋਲ"</string>
+    <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ਚਾਲੂ"</string>
+    <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"ਬੰਦ"</string>
+    <string name="option_channels_locked" msgid="5797855082297549907">"ਚੈਨਲ ਬਲੌਕ ਕੀਤੇ ਗਏ"</string>
+    <string name="option_channels_lock_all" msgid="6594512884477342940">"ਸਭ ਬਲੌਕ ਕਰੋ"</string>
+    <string name="option_channels_unlock_all" msgid="6839513296447567623">"ਸਭ ਅਣਬਲੌਕ ਕਰੋ"</string>
+    <string name="option_channels_subheader_hidden" msgid="4669425935426972078">"ਲੁਕੇ ਹੋਏ ਚੈਨਲ"</string>
+    <string name="option_program_restrictions" msgid="241342023067364108">"ਪ੍ਰੋਗਰਾਮ ਪਾਬੰਦੀਆਂ"</string>
+    <string name="option_change_pin" msgid="2881594075631152566">"PIN ਬਦਲੋ"</string>
+    <string name="option_country_rating_systems" msgid="7288569813945260224">"ਰੇਟਿੰਗ ਸਿਸਟਮ"</string>
+    <string name="option_ratings" msgid="4009116954188688616">"ਰੇਟਿੰਗਾਂ"</string>
+    <string name="option_see_all_rating_systems" msgid="7702673500014877288">"ਸਭ ਰੇਟਿੰਗ ਸਿਸਟਮ ਵੇਖੋ"</string>
+    <string name="other_countries" msgid="8342216398676184749">"ਹੋਰ ਦੇਸ਼"</string>
+    <string name="option_no_locked_channel" msgid="2543094883927978444">"ਕੋਈ ਨਹੀਂ"</string>
+    <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ਕੋਈ ਨਹੀਂ"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"ਰੇਟਿੰਗ-ਰਹਿਤ"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"ਰੇਟਿੰਗ-ਰਹਿਤ ਪ੍ਰੋਗਰਾਮ ਬਲੌਕ ਕਰੋ"</string>
+    <string name="option_rating_none" msgid="5204552587760414879">"ਕੋਈ ਨਹੀਂ"</string>
+    <string name="option_rating_high" msgid="8898400296730158893">"ਉੱਚ ਪਾਬੰਦੀਆਂ"</string>
+    <string name="option_rating_medium" msgid="6455853836426497151">"ਦਰਮਿਆਨੀਆਂ ਪਾਬੰਦੀਆਂ"</string>
+    <string name="option_rating_low" msgid="5800146024503377969">"ਘੱਟ ਪਾਬੰਦੀਆਂ"</string>
+    <string name="option_rating_custom" msgid="3155377834510646436">"ਵਿਸ਼ੇਸ਼-ਵਿਉਂਤਬੱਧ"</string>
+    <string name="option_rating_high_description" msgid="609567565273278745">"ਬੱਚਿਆਂ ਲਈ ਉਚਿਤ ਸਮੱਗਰੀ"</string>
+    <string name="option_rating_medium_description" msgid="7169199016608935280">"ਵੱਡੇ ਬੱਚਿਆਂ ਲਈ ਉਚਿਤ ਸਮੱਗਰੀ"</string>
+    <string name="option_rating_low_description" msgid="4740109576615335045">"ਅੱਲੜ੍ਹਾਂ ਲਈ ਉਚਿਤ ਸਮੱਗਰੀ"</string>
+    <string name="option_rating_custom_description" msgid="6180723522991233194">"ਦਸਤੀ ਪਾਬੰਦੀਆਂ"</string>
+    <string name="option_attribution" msgid="2967657807178951562">"ਰੇਟਿੰਗ ਵਰਣਨਾਂ ਲਈ ਸਰੋਤ"</string>
+    <string name="option_subrating_title" msgid="5485055507818077595">"%1$s ਅਤੇ ਉੱਪ-ਰੇਟਿੰਗਾਂ"</string>
+    <string name="option_subrating_header" msgid="4637961301549615855">"ਉੱਪ-ਰੇਟਿੰਗਾਂ"</string>
+    <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"ਇਹ ਚੈਨਲ ਦੇਖਣ ਲਈ ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="pin_enter_unlock_program" msgid="7311628843209871203">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਦੇਖਣ ਲਈ ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"ਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ <xliff:g id="RATING">%1$s</xliff:g> ਰੇਟ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ ਵੇਖਣ ਲਈ ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਰੇਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ ਦੇਖਣ ਲਈ ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="pin_enter_pin" msgid="249314665028035038">"ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="pin_enter_create_pin" msgid="3385754356793309946">"ਮਾਪਿਆਂ ਦੇ ਕੰਟਰੋਲਾਂ ਨੂੰ ਸੈੱਟ ਕਰਨ ਲਈ, ਇੱਕ PIN ਬਣਾਓ"</string>
+    <string name="pin_enter_new_pin" msgid="1739471585849790384">"ਨਵਾਂ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="pin_enter_again" msgid="2618999754723090427">"ਆਪਣੇ PIN ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
+    <string name="pin_enter_old_pin" msgid="4588282612931041919">"ਆਪਣਾ ਮੌਜੂਦਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <plurals name="pin_enter_countdown" formatted="false" msgid="3415233538538544309">
+      <item quantity="one">ਤੁਸੀਂ 5 ਵਾਰ ਗਲਤ PIN ਦਾਖਲ ਕੀਤਾ\n<xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> ਸਕਿੰਟ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ</item>
+      <item quantity="other">ਤੁਸੀਂ 5 ਵਾਰ ਗਲਤ PIN ਦਾਖਲ ਕੀਤਾ\n<xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ</item>
+    </plurals>
+    <string name="pin_toast_wrong" msgid="2126295626095048746">"ਉਹ PIN ਗਲਤ ਸੀ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="pin_toast_not_match" msgid="4283624338659521768">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ, PIN ਮੇਲ ਨਹੀਂ ਖਾਂਦਾ"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"ਆਪਣਾ ਜ਼ਿਪ ਕੋਡ ਦਾਖਲ ਕਰੋ।"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"ਲਾਈਵ ਚੈਨਲ ਐਪ ਟੀਵੀ ਚੈਨਲਾਂ ਲਈ ਮੁਕੰਮਲ ਪ੍ਰੋਗਰਾਮ ਗਾਈਡ ਮੁਹੱਈਆ ਕਰਵਾਉਣ ਵਾਸਤੇ ਜ਼ਿਪ ਕੋਡ ਦੀ ਵਰਤੋਂ ਕਰੇਗੀ।"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"ਆਪਣਾ ਜ਼ਿਪ ਕੋਡ ਦਾਖਲ ਕਰੋ"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"ਅਵੈਧ ਜ਼ਿਪ ਕੋਡ"</string>
+    <string name="side_panel_title_settings" msgid="8244327316510918755">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"ਚੈਨਲ ਸੂਚੀ ਨੂੰ ਵਿਸ਼ੇਸ਼ ਵਿਉਂਤਬੱਧ ਕਰੋ"</string>
+    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"ਆਪਣੀ ਪ੍ਰੋਗਰਾਮ ਗਾਈਡ ਲਈ ਚੈਨਲ ਚੁਣੋ"</string>
+    <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"ਚੈਨਲ ਸਰੋਤ"</string>
+    <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"ਨਵੇਂ ਚੈਨਲ ਉਪਲਬਧ ਹਨ"</string>
+    <string name="settings_parental_controls" msgid="5449397921700749317">"ਮਾਪਿਆਂ ਦੇ ਕੰਟਰੋਲ"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"ਟਾਈਮ-ਸ਼ਿਫਟ"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"ਟੀਵੀ ਦੇਖਣ ਦੌਰਾਨ ਰਿਕਾਰਡ ਕਰੋ ਤਾਂ ਕਿ ਤੁਸੀਂ ਲਾਈਵ ਪ੍ਰੋਗਰਾਮਾਂ ਨੂੰ ਰੋਕ ਜਾਂ ਪਿੱਛੇ ਲੈ ਜਾ ਸਕੋਂ।\nਚਿਤਾਵਨੀ: ਇਸ ਨਾਲ ਸਟੋਰੇਜ ਦੀ ਵੱਧ ਵਰਤੋਂ ਹੋਣ ਕਰਕੇ ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ ਦਾ ਜੀਵਨਕਾਲ ਘੱਟ ਹੋ ਸਕਦਾ ਹੈ।"</string>
+    <string name="settings_menu_licenses" msgid="1257646083838406103">"ਖੁੱਲ੍ਹਾ ਸਰੋਤ ਲਾਇਸੰਸ"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ਪ੍ਰਤੀਕਰਮ ਭੇਜੋ"</string>
+    <string name="settings_menu_version" msgid="2604030372029921403">"ਰੂਪ"</string>
+    <string name="tvview_channel_locked" msgid="6486375335718400728">"ਇਸ ਚੈਨਲ ਨੂੰ ਵੇਖਣ ਲਈ, &amp;apos;ਸੱਜਾ&amp;apos; ਬਟਨ ਦਬਾਓ ਅਤੇ ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="tvview_content_locked" msgid="391823084917017730">"ਇਸ ਚੈਨਲ ਨੂੰ ਵੇਖਣ ਲਈ, &amp;apos;ਸੱਜਾ&amp;apos; ਬਟਨ ਦਬਾਓ ਅਤੇ ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਰੇਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ।\nਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ ਦੇਖਣ ਲਈ, ਸੱਜਾ ਬਟਨ ਦਬਾਓ ਅਤੇ ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ"</string>
+    <string name="tvview_content_locked_format" msgid="3741874636031338247">"ਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ <xliff:g id="RATING">%1$s</xliff:g> ਰੇਟ ਕੀਤਾ ਗਿਆ ਹੈ।\nਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ ਵੇਖਣ ਲਈ, &amp;apos;ਸੱਜਾ&amp;apos; ਬਟਨ ਦਬਾਓ ਅਤੇ ਆਪਣਾ PIN ਦਾਖਲ ਕਰੋ।"</string>
+    <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ਇਸ ਚੈਨਲ ਨੂੰ ਵੇਖਣ ਲਈ, ਪੂਰਵ-ਨਿਰਧਾਰਤ ਲਾਈਵ ਟੀਵੀ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string>
+    <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"ਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ ਵੇਖਣ ਲਈ, ਪੂਰਵ-ਨਿਰਧਾਰਤ ਲਾਈਵ ਟੀਵੀ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਰੇਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ।\nਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ ਦੇਖਣ ਲਈ, ਪੂਰਵ-ਨਿਰਧਾਰਤ ਲਾਈਵ ਟੀਵੀ ਅੈਪ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string>
+    <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"ਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ <xliff:g id="RATING">%1$s</xliff:g> ਰੇਟ ਕੀਤਾ ਗਿਆ ਹੈ।\nਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ ਵੇਖਣ ਲਈ, ਪੂਰਵ-ਨਿਰਧਾਰਤ ਲਾਈਵ ਟੀਵੀ ਐਪ ਦੀ ਵਰਤੋਂ ਕਰੋ।"</string>
+    <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"ਪ੍ਰੋਗਰਾਮ ਬਲੌਕ ਕੀਤਾ ਹੋਇਆ ਹੈ"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਰੇਟ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+    <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"ਇਸ ਪ੍ਰੋਗਰਾਮ ਨੂੰ <xliff:g id="RATING">%1$s</xliff:g> ਰੇਟ ਕੀਤਾ ਗਿਆ ਹੈ"</string>
+    <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ਸਿਰਫ ਔਡੀਓ"</string>
+    <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"ਕਮਜ਼ੋਰ ਸਿਗਨਲ"</string>
+    <string name="tvview_msg_no_internet_connection" msgid="7655994401188888231">"ਕੋਈ ਇੰਟਰਨੈੱਟ ਕਨੈਕਸ਼ਨ ਨਹੀਂ"</string>
+    <plurals name="tvview_msg_input_no_resource" formatted="false" msgid="8581894855153658823">
+      <item quantity="one">ਇਸ ਚੈਨਲ ਨੂੰ <xliff:g id="END_TIME_1">%1$s</xliff:g> ਤੱਕ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ ਕਿਉਂਕਿ ਹੋਰ ਚੈਨਲ ਰਿਕਾਰਡ ਕੀਤੇ ਜਾ ਰਹੇ ਹਨ। \n\nਰਿਕਾਰਡਿੰਗ ਦੇ ਨਿਯਤ ਸਮੇਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ &amp;apos;ਸੱਜਾ&amp;apos; ਬਟਨ ਦਬਾਓ।</item>
+      <item quantity="other">ਇਸ ਚੈਨਲ ਨੂੰ <xliff:g id="END_TIME_1">%1$s</xliff:g> ਤੱਕ ਨਹੀਂ ਚਲਾਇਆ ਜਾ ਸਕਦਾ ਕਿਉਂਕਿ ਹੋਰ ਚੈਨਲ ਰਿਕਾਰਡ ਕੀਤੇ ਜਾ ਰਹੇ ਹਨ। \n\nਰਿਕਾਰਡਿੰਗ ਦੇ ਨਿਯਤ ਸਮੇਂ ਨੂੰ ਵਿਵਸਥਿਤ ਕਰਨ ਲਈ &amp;apos;ਸੱਜਾ&amp;apos; ਬਟਨ ਦਬਾਓ।</item>
+    </plurals>
+    <string name="channel_banner_no_title" msgid="8660301979190693176">"ਕੋਈ ਸਿਰਲੇਖ ਨਹੀਂ"</string>
+    <string name="channel_banner_locked_channel_title" msgid="2006564967318945980">"ਚੈਨਲ ਬਲੌਕ ਹੈ"</string>
+    <string name="setup_category_new" msgid="2899355289563443627">"ਨਵਾਂ"</string>
+    <string name="setup_category_done" msgid="4750902502852212319">"ਸਰੋਤ"</string>
+    <plurals name="setup_input_channels" formatted="false" msgid="1695941684075602971">
+      <item quantity="one">%1$d ਚੈਨਲ</item>
+      <item quantity="other">%1$d ਚੈਨਲ</item>
+    </plurals>
+    <string name="setup_input_no_channels" msgid="1669327912393163331">"ਕੋਈ ਚੈਨਲ ਉਪਲਬਧ ਨਹੀਂ ਹਨ"</string>
+    <string name="setup_input_new" msgid="3337725672277046798">"ਨਵਾਂ"</string>
+    <string name="setup_input_setup_now" msgid="1772000402336958967">"ਸਥਾਪਤ ਨਹੀਂ"</string>
+    <string name="setup_store_action_title" msgid="4083402039720973414">"ਹੋਰ ਸਰੋਤ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"ਲਾਈਵ ਚੈਨਲਾਂ ਦੀ ਪੇਸ਼ਕਸ਼ ਕਰਦੀਆਂ ਐਪਾਂ ਨੂੰ ਬ੍ਰਾਊਜ਼ ਕਰੋ"</string>
+    <string name="new_sources_title" msgid="3878933676500061895">"ਨਵੇਂ ਚੈਨਲ ਸਰੋਤ ਉਪਲਬਧ ਹਨ"</string>
+    <string name="new_sources_description" msgid="749649005588426813">"ਨਵੇਂ ਚੈਨਲ ਸਰੋਤਾਂ ਕੋਲ ਪੇਸ਼ਕਸ਼ ਕਰਨ ਲਈ ਚੈਨਲ ਹਨ।\nਉਹਨਾਂ ਨੂੰ ਹੁਣੇ ਸਥਾਪਤ ਕਰੋ, ਜਾਂ ਇਹ ਬਾਅਦ ਵਿੱਚ ਚੈਨਲ ਸਰੋਤ ਸੈਟਿੰਗ ਵਿੱਚ ਕਰੋ।"</string>
+    <string name="new_sources_action_setup" msgid="177693761664016811">"ਹੁਣੇ ਸਥਾਪਤ ਕਰੋ"</string>
+    <string name="new_sources_action_skip" msgid="2501296961258184330">"ਠੀਕ, ਸਮਝ ਲਿਆ"</string>
+    <!-- no translation found for intro_title (251772896916795556) -->
+    <skip />
+    <string name="intro_description" msgid="7806473686446937307">"ਟੀਵੀ ਮੀਨੂ \'ਤੇ ਪਹੁੰਚ ਪ੍ਰਾਪਤ ਕਰਨ ਲਈ "<b>"&amp;apos;ਚੁਣੋ&amp;apos; ਨੂੰ ਦਬਾਓ"</b>"।"</string>
+    <string name="msg_no_input" msgid="3897674146985427865">"ਕੋਈ ਟੀਵੀ ਇਨਪੁਟ ਨਹੀਂ ਲੱਭੀ"</string>
+    <string name="msg_no_specific_input" msgid="2688885987104249852">"ਟੀਵੀ ਇਨਪੁਟ ਨੂੰ ਲੱਭਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ"</string>
+    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ਟਿਊਨਰ ਦੀ ਕਿਸਮ ਉਚਿਤ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਟਿਊਨਰ ਕਿਸਮ ਦੀ ਟੀਵੀ ਇਨਪੁਟ ਲਈ ਲਾਈਵ ਚੈਨਲ ਐਪ ਨੂੰ ਲਾਂਚ ਕਰੋ।"</string>
+    <string name="msg_tune_failed" msgid="3277419551849972252">"ਟਿਊਨ ਅਸਫ਼ਲ ਰਿਹਾ"</string>
+    <string name="msg_missing_app" msgid="8291542072400042076">"ਇਸ ਕਾਰਵਾਈ ਨਾਲ ਨਿਪਟਣ ਲਈ ਕੋਈ ਐਪ ਨਹੀਂ ਲੱਭੀ।"</string>
+    <string name="msg_all_channels_hidden" msgid="777397634062471936">"ਸਾਰੇ ਸਰੋਤ ਚੈਨਲ ਲੁਕੇ ਹੋਏ ਹਨ।\nਵੇਖਣ ਲਈ ਘੱਟੋ-ਘੱਟ ਇੱਕ ਚੈਨਲ ਨੂੰ ਚੁਣੋ।"</string>
+    <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"ਵੀਡੀਓ ਫ਼ਾਈਲ ਅਣਕਿਆਸੇ ਤਰੀਕੇ ਨਾਲ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
+    <string name="msg_back_key_guide" msgid="7404682718828721924">"&amp;apos;ਪਿੱਛੇ&amp;apos; ਕੁੰਜੀ ਕਨੈਕਟ ਕੀਤੀ ਡੀਵਾਈਸ ਲਈ ਹੈ। ਬਾਹਰ ਜਾਣ ਲਈ ਹੋਮ ਬਟਨ ਦਬਾਓ।"</string>
+    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"ਲਾਈਵ ਚੈਨਲਾਂ ਨੂੰ ਟੀਵੀ ਸੂਚੀਆਂ ਪੜ੍ਹਨ ਲਈ ਇਜਾਜ਼ਤ ਦੀ ਲੋੜ ਹੈ।"</string>
+    <string name="setup_sources_text" msgid="4988039637873759839">"ਆਪਣੇ ਸਰੋਤਾਂ ਦੀ ਸਥਾਪਨਾ ਕਰੋ"</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"ਲਾਈਵ ਚੈਨਲ ਐਪ ਰਵਾਇਤੀ ਟੀਵੀ ਚੈਨਲਾਂ ਦੇ ਅਨੁਭਵ ਨਾਲ ਐਪਾਂ ਦੁਆਰਾ ਮੁਹੱਈਆ ਕੀਤੇ ਸਟ੍ਰੀਮਿੰਗ ਚੈਨਲਾਂ ਦੇ ਅਨੁਭਵ ਨੂੰ ਮਿਲਾਉਂਦੀ ਹੈ। \n\nਪਹਿਲਾਂ ਤੋਂ ਸਥਾਪਤ ਕੀਤੇ ਚੈਨਲ ਸਰੋਤਾਂ ਦੀ ਸਥਾਪਨਾ ਕਰਕੇ ਸ਼ੁਰੂ ਕਰੋ। ਜਾਂ ਲਾਈਵ ਚੈਨਲਾਂ ਦੀ ਪੇਸ਼ਕਸ਼ ਕਰਦੀਆਂ ਹੋਰ ਐਪਾਂ ਲਈ Google Play ਸਟੋਰ ਨੂੰ ਬ੍ਰਾਊਜ਼ ਕਰੋ।"</string>
+    <string name="channels_item_dvr" msgid="8911915252648532469">"ਰਿਕਾਰਡਿੰਗ ਅਤੇ ਨਿਯਤ ਸਮੇਂ"</string>
+    <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 ਮਿੰਟ"</string>
+    <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 ਮਿੰਟ"</string>
+    <string name="recording_start_dialog_1_hour_duration" msgid="7159533207022355641">"1 ਘੰਟਾ"</string>
+    <string name="recording_start_dialog_3_hours_duration" msgid="295984419320006238">"3 ਘੰਟੇ"</string>
+    <string name="dvr_main_recent" msgid="2553805424822806495">"ਹਾਲੀਆ"</string>
+    <string name="dvr_main_scheduled" msgid="7837260963086408492">"ਨਿਯਤ"</string>
+    <string name="dvr_main_series" msgid="8278256687595691676">"ਲੜੀ"</string>
+    <string name="dvr_main_others" msgid="2970835573614038153">"ਹੋਰ"</string>
+    <string name="dvr_msg_cannot_record_channel" msgid="6836291367918532447">"ਚੈਨਲ ਨੂੰ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
+    <string name="dvr_msg_cannot_record_program" msgid="4184046342810946090">"ਪ੍ਰੋਗਰਾਮ ਨੂੰ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
+    <string name="dvr_msg_program_scheduled" msgid="3800847542300367572">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਲਈ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ।"</string>
+    <string name="dvr_msg_current_program_scheduled" msgid="2505247201782991463">"ਹੁਣ ਤੋਂ <xliff:g id="ENDTIME">%2$s</xliff:g> ਤੱਕ <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
+    <string name="dvr_full_schedule_card_view_title" msgid="7198521806965950089">"ਸੰਪੂਰਨ ਕਾਰਜ-ਕ੍ਰਮ"</string>
+    <plurals name="dvr_full_schedule_card_view_content" formatted="false" msgid="790788122541080768">
+      <item quantity="one">ਅਗਲਾ %1$d ਦਿਨ</item>
+      <item quantity="other">ਅਗਲੇ %1$d ਦਿਨ</item>
+    </plurals>
+    <plurals name="dvr_program_duration" formatted="false" msgid="6742119148312354741">
+      <item quantity="one">%1$d ਮਿੰਟ</item>
+      <item quantity="other">%1$d ਮਿੰਟ</item>
+    </plurals>
+    <plurals name="dvr_count_new_recordings" formatted="false" msgid="3569310208305402815">
+      <item quantity="one">%1$d ਨਵੀਂ ਰਿਕਾਰਡਿੰਗ</item>
+      <item quantity="other">%1$d ਨਵੀਆਂ ਰਿਕਾਰਡਿੰਗਾਂ</item>
+    </plurals>
+    <plurals name="dvr_count_recordings" formatted="false" msgid="7417379223468131391">
+      <item quantity="one">%1$d ਰਿਕਾਰਡਿੰਗ</item>
+      <item quantity="other">%1$d ਰਿਕਾਰਡਿੰਗਾਂ</item>
+    </plurals>
+    <plurals name="dvr_count_scheduled_recordings" formatted="false" msgid="1650330290765214511">
+      <item quantity="one">%1$d ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ</item>
+      <item quantity="other">%1$d ਰਿਕਾਰਡਿੰਗਾਂ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ</item>
+    </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"ਰਿਕਾਰਡਿੰਗ ਰੱਦ ਕਰੋ"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"ਰਿਕਾਰਡਿੰਗ ਬੰਦ ਕਰੋ"</string>
+    <string name="dvr_detail_watch" msgid="7085694764364338215">"ਵੇਖੋ"</string>
+    <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"ਮੁੱਢ ਤੋਂ ਚਲਾਓ"</string>
+    <string name="dvr_detail_resume_play" msgid="875591300274416373">"ਜਿੱਥੇ ਛੱਡਿਆ ਸੀ ਓਥੋਂ ਦੁਬਾਰਾ ਚਲਾਓ"</string>
+    <string name="dvr_detail_delete" msgid="4535881013528321898">"ਮਿਟਾਓ"</string>
+    <string name="dvr_detail_series_delete" msgid="4831926831670312674">"ਰਿਕਾਰਡਿੰਗਾਂ ਮਿਟਾਓ"</string>
+    <string name="dvr_detail_series_resume" msgid="6935136228671386246">"ਮੁੜ ਸ਼ੁਰੂ ਕਰੋ"</string>
+    <string name="dvr_detail_series_season_title" msgid="5474850936497854790">"ਸੀਜ਼ਨ <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>"</string>
+    <string name="dvr_detail_view_schedule" msgid="7137536927421904426">"ਕਾਰਜ-ਕ੍ਰਮ ਵੇਖੋ"</string>
+    <string name="dvr_detail_read_more" msgid="2588920758094498544">"ਹੋਰ ਪੜ੍ਹੋ"</string>
+    <string name="dvr_series_deletion_title" msgid="7672649492494507574">"ਰਿਕਾਰਡਿੰਗਾਂ ਮਿਟਾਓ"</string>
+    <string name="dvr_series_deletion_description" msgid="994839237906552969">"ਉਹਨਾਂ ਐਪੀਸੋਡਾਂ ਨੂੰ ਚੁਣੋ ਜਿੰਨ੍ਹਾਂ ਨੂੰ ਤੁਸੀਂ ਮਿਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ। ਇੱਕ ਵਾਰ ਮਿਟਾਏ ਜਾਣ ਤੋਂ ਬਾਅਦ ਉਹਨਾਂ ਨੂੰ ਮੁੜ-ਹਾਸਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
+    <string name="dvr_series_deletion_no_recordings" msgid="481210819034514">"ਮਿਟਾਉਣ ਲਈ ਕੋਈ ਰਿਕਾਰਡਿੰਗਾਂ ਨਹੀਂ ਹਨ।"</string>
+    <string name="dvr_series_select_watched" msgid="3608122404146716502">"ਵੇਖੇ ਗਏ ਐਪੀਸੋਡ ਚੁਣੋ"</string>
+    <string name="dvr_series_select_all" msgid="5415749261739544048">"ਸਾਰੇ ਐਪੀਸੋਡ ਚੁਣੋ"</string>
+    <string name="dvr_series_deselect_all" msgid="1680395960166387572">"ਸਾਰੇ ਐਪੀਸੋਡਾਂ ਨੂੰ ਅਣਚੁਣਿਆ ਕਰੋ"</string>
+    <string name="dvr_series_watched_info_minutes" msgid="5656926431901526030">"<xliff:g id="DURATION">%2$d</xliff:g> ਵਿੱਚੋਂ <xliff:g id="WATCHED">%1$d</xliff:g> ਮਿੰਟਾਂ ਦੀ ਰਿਕਾਰਡਿੰਗ ਵੇਖੀ ਗਈ"</string>
+    <string name="dvr_series_watched_info_seconds" msgid="2667537184197566662">"<xliff:g id="DURATION">%2$d</xliff:g> ਵਿੱਚੋਂ <xliff:g id="WATCHED">%1$d</xliff:g> ਸਕਿੰਟਾਂ ਦੀ ਰਿਕਾਰਡਿੰਗ ਵੇਖੀ ਗਈ"</string>
+    <string name="dvr_series_never_watched" msgid="6086008065876122655">"ਕਦੇ ਵੀ ਨਾ ਦੇਖੀਆਂ"</string>
+    <plurals name="dvr_msg_episodes_deleted" formatted="false" msgid="5627112959798353905">
+      <item quantity="one">%2$d ਵਿੱਚੋਂ %1$d ਐਪੀਸੋਡ ਮਿਟਾਇਆ ਗਿਆ ਹੈ</item>
+      <item quantity="other">%2$d ਵਿੱਚੋਂ %1$d ਐਪੀਸੋਡ ਮਿਟਾਏ ਗਏ ਹਨ</item>
+    </plurals>
+    <string name="dvr_series_settings_priority" msgid="5836437092774185710">"ਤਰਜੀਹ"</string>
+    <string name="dvr_series_settings_priority_highest" msgid="1072006447796648382">"ਉੱਚਤਮ"</string>
+    <string name="dvr_series_settings_priority_lowest" msgid="6003996497908810225">"ਨਿਊਨਤਮ"</string>
+    <string name="dvr_series_settings_priority_rank" msgid="667778382820956116">"ਨੰਬਰ <xliff:g id="RANK">%1$d</xliff:g>"</string>
+    <string name="dvr_series_settings_channels" msgid="3164900110165729909">"ਚੈਨਲ"</string>
+    <string name="dvr_series_settings_channels_all" msgid="656434955168572976">"ਕੋਈ ਵੀ"</string>
+    <string name="dvr_priority_title" msgid="1537886929061487213">"ਤਰਜੀਹ ਚੁਣੋ"</string>
+    <string name="dvr_priority_description" msgid="8362040921417154645">"ਜਦੋਂ ਇੱਕੋ ਸਮੇਂ ਰਿਕਾਰਡ ਕਰਨ ਲਈ ਬਹੁਤ ਜ਼ਿਆਦਾ ਪ੍ਰੋਗਰਾਮ ਹੋਣ, ਤਾਂ ਸਿਰਫ਼ ਸਭ ਤੋਂ ਵੱਧ ਤਰਜੀਹ ਵਾਲੇ ਪ੍ਰੋਗਰਾਮ ਹੀ ਰਿਕਾਰਡ ਕੀਤੇ ਜਾਣਗੇ।"</string>
+    <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"ਰੱਖਿਅਤ ਕਰੋ"</string>
+    <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ਇੱਕ ਵਾਰ ਕੀਤੀਆਂ ਜਾਣ ਵਾਲੀਆਂ ਰਿਕਾਰਡਿੰਗਾਂ ਦੀ ਉੱਚਤਮ ਤਰਜੀਹ ਹੁੰਦੀ ਹੈ"</string>
+    <string name="dvr_action_stop" msgid="1378723485295471381">"ਬੰਦ ਕਰੋ"</string>
+    <string name="dvr_action_view_schedules" msgid="7442990695392774263">"ਰਿਕਾਰਡਿੰਗ ਦਾ ਨਿਯਤ ਸਮਾਂ ਵੇਖੋ"</string>
+    <string name="dvr_action_record_episode" msgid="8596182676610326327">"ਇਹ ਸਿੰਗਲ ਪ੍ਰੋਗਰਾਮ"</string>
+    <string name="dvr_action_record_episode_from_now_description" msgid="5125122951529985697">"ਹੁਣ - <xliff:g id="ENDTIME">%1$s</xliff:g>"</string>
+    <string name="dvr_action_record_series" msgid="8501991316179436899">"ਸਮੁੱਚੀ ਲੜੀਆਂ …"</string>
+    <string name="dvr_action_record_anyway" msgid="991470058034937231">"ਫਿਰ ਵੀ ਨਿਯਤ ਕਰੋ"</string>
+    <string name="dvr_action_record_instead" msgid="6821164728752215738">"ਇਸ ਦੀ ਬਜਾਏ ਇਸ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string>
+    <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ਇਸ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਰੱਦ ਕਰੋ"</string>
+    <string name="dvr_action_watch_now" msgid="7181211920959075976">"ਹੁਣ ਵੇਖੋ"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ਰਿਕਾਰਡਿੰਗਾਂ ਮਿਟਾਓ…"</string>
+    <string name="dvr_epg_program_recordable" msgid="609229576209476903">"ਰਿਕਾਰਡ ਕਰਨ ਯੋਗ"</string>
+    <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ਰਿਕਾਰਡਿੰਗ ਵਿਵਾਦ"</string>
+    <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"ਰਿਕਾਰਡਿੰਗ"</string>
+    <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ਰਿਕਾਰਡਿੰਗ ਅਸਫਲ ਰਹੀ"</string>
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"ਪ੍ਰੋਗਰਾਮਾਂ ਨੂੰ ਪੜ੍ਹਿਆ ਜਾ ਰਿਹਾ ਹੈ"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"ਹਾਲੀਆ ਰਿਕਾਰਡਿੰਗਾਂ ਵੇਖੋ"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ਦੀ ਰਿਕਾਰਡਿੰਗ ਅਧੂਰੀ ਹੈ।"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ਅਤੇ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ਦੀਆਂ ਰਿਕਾਰਡਿੰਗਾਂ ਅਧੂਰੀਆਂ ਹਨ।"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ਅਤੇ <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ਦੀਆਂ ਰਿਕਾਰਡਿੰਗਾਂ ਅਧੂਰੀਆਂ ਹਨ।"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ ਨਾ ਹੋਣ ਕਰਕੇ <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ਦੀ ਰਿਕਾਰਡਿੰਗ ਪੂਰੀ ਨਹੀਂ ਹੋਈ।"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ ਨਾ ਹੋਣ ਕਰਕੇ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ਅਤੇ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ਦੀਆਂ ਰਿਕਾਰਡਿੰਗਾਂ ਪੂਰੀਆਂ ਨਹੀਂ ਹੋਈਆਂ।"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"ਲੋੜੀਂਦੀ ਸਟੋਰੇਜ ਨਾ ਹੋਣ ਕਰਕੇ <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ਅਤੇ <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ਦੀਆਂ ਰਿਕਾਰਡਿੰਗਾਂ ਪੂਰੀਆਂ ਨਹੀਂ ਹੋਈਆਂ।"</string>
+    <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR ਨੂੰ ਹੋਰ ਸਟੋਰੇਜ ਦੀ ਲੋੜ ਹੈ"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ਤੁਸੀਂ DVR ਨਾਲ ਪ੍ਰੋਗਰਾਮਾਂ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਸਕੋਂਗੇ। ਹਾਲਾਂਕਿ ਹੁਣ DVR ਦੇ ਕੰਮ ਕਰਨ ਲਈ ਤੁਹਾਡੀ ਡੀਵਾਈਸ ਵਿਚਲੀ ਸਟੋਰੇਜ ਕਾਫੀ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB ਜਾਂ ਉਸਤੋਂ ਵੀ ਜ਼ਿਆਦਾ ਸਟੋਰੇਜ ਵਾਲੀ ਬਾਹਰੀ ਡੀਵਾਈਸ ਨੂੰ ਕਨੈਕਟ ਕਰੋ ਅਤੇ ਉਸ ਨੂੰ ਡੀਵਾਈਸ ਸਟੋਰੇਜ ਵਜੋਂ ਵੰਨਗੀਕਿਰਤ ਕਰਨ ਲਈ ਪੜਾਵਾਂ ਦਾ ਅਨੁਸਰਣ ਕਰੋ।"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"ਸਟੋਰੇਜ ਕਾਫੀ ਨਹੀਂ ਹੈ"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ ਕਿਉਂਕਿ ਸਟੋਰੇਜ ਕਾਫ਼ੀ ਨਹੀਂ ਹੈ। ਪਹਿਲਾਂ ਤੋਂ ਮੌਜੂਦ ਕੁਝ ਰਿਕਾਰਡਿੰਗਾਂ ਨੂੰ ਮਿਟਾਉਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
+    <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"ਸਟੋਰੇਜ ਨਹੀਂ ਹੈ"</string>
+    <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"ਰਿਕਾਰਡਿੰਗ ਬੰਦ ਕਰਨੀ ਹੈ?"</string>
+    <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"ਰਿਕਾਰਡ ਕੀਤੀ ਸਮੱਗਰੀ ਨੂੰ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ਦੀ ਰਿਕਾਰਡਿੰਗ ਬੰਦ ਹੋ ਜਾਵੇਗੀ ਕਿਉਂਕਿ ਇਹ ਇਸ ਪ੍ਰੋਗਰਾਮ ਨਾਲ ਵਿਵਾਦ ਕਰਦੀ ਹੈ। ਰਿਕਾਰਡ ਕੀਤੀ ਸਮੱਗਰੀ ਰੱਖਿਅਤ ਕੀਤੀ ਜਾਵੇਗੀ।"</string>
+    <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਪਰ ਇਸ ਵਿੱਚ ਵਿਵਾਦ ਹਨ"</string>
+    <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਹੋ ਗਈ ਹੈ ਪਰ ਇਸ ਵਿੱਚ ਵਿਵਾਦ ਹਨ"</string>
+    <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="dvr_channel_conflict_dialog_description_prefix" msgid="212344250779878791">"<xliff:g id="CHANNELNAME">%1$s</xliff:g> ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ।"</string>
+    <string name="dvr_program_conflict_dialog_description_1" msgid="2278200346765501164">"<xliff:g id="CONFLICTPROGRAMNAME">%1$s</xliff:g> ਦੇ ਕੁਝ ਹਿੱਸੇ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤੇ ਜਾਣਗੇ।"</string>
+    <string name="dvr_program_conflict_dialog_description_2" msgid="5648524408147235696">"<xliff:g id="CONFLICTPROGRAMNAME_1">%1$s</xliff:g> ਅਤੇ <xliff:g id="CONFLICTPROGRAMNAME_2">%2$s</xliff:g> ਦੇ ਕੁਝ ਹਿੱਸੇ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤੇ ਜਾਣਗੇ।"</string>
+    <string name="dvr_program_conflict_dialog_description_3" msgid="6879199850098595108">"<xliff:g id="CONFLICTPROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2">%2$s</xliff:g> ਅਤੇ ਇੱਕ ਹੋਰ ਨਿਯਤ ਕੀਤੇ ਸਮੇਂ ਵਾਲੇ ਪ੍ਰੋਗਰਾਮਾਂ ਦੇ ਕੁਝ ਹਿੱਸੇ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤੇ ਜਾਣਗੇ।"</string>
+    <plurals name="dvr_program_conflict_dialog_description_many" formatted="false" msgid="1008340710252647947">
+      <item quantity="one"><xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> ਅਤੇ %3$d ਨਿਯਤ ਕੀਤੇ ਸਮੇਂ ਦੇ ਕੁਝ ਹਿੱਸੇ ਨੂੰ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</item>
+      <item quantity="other"><xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> ਅਤੇ %3$d ਨਿਯਤ ਕੀਤੇ ਸਮਿਆਂ ਦੇ ਕੁਝ ਹਿੱਸੇ ਨੂੰ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</item>
+    </plurals>
+    <string name="dvr_schedule_dialog_title" msgid="5235629824986156058">"ਤੁਸੀਂ ਕੀ ਰਿਕਾਰਡ ਕਰਨਾ ਚਾਹੋਂਗੇ?"</string>
+    <string name="dvr_channel_record_duration_dialog_title" msgid="4601361040431047918">"ਤੁਸੀਂ ਕਿੰਨਾ ਚਿਰ ਰਿਕਾਰਡ ਕਰਨਾ ਚਾਹੋਂਗੇ?"</string>
+    <string name="dvr_already_scheduled_dialog_title" msgid="4525318291210934311">"ਪਹਿਲਾਂ ਹੀ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ"</string>
+    <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"ਉਸੇ ਪ੍ਰੋਗਰਾਮ ਦਾ <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> \'ਤੇ ਰਿਕਾਰਡ ਕੀਤੇ ਜਾਣ ਲਈ ਪਹਿਲਾਂ ਤੋਂ ਹੀ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ।"</string>
+    <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"ਪਹਿਲਾਂ ਹੀ ਰਿਕਾਰਡ ਕੀਤਾ ਹੋਇਆ ਹੈ"</string>
+    <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"ਇਹ ਪ੍ਰੋਗਰਾਮ ਪਹਿਲਾਂ ਹੀ ਰਿਕਾਰਡ ਕੀਤਾ ਹੋਇਆ ਹੈ। ਇਹ DVR ਲਾਇਬ੍ਰੇਰੀ ਵਿੱਚ ਉਪਲਬਧ ਹੈ।"</string>
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"ਲੜੀ ਦੀ ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ।</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗਾਂ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ।</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਉਹਨਾਂ ਵਿੱਚੋਂ <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ਨੂੰ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗਾਂ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਉਹਨਾਂ ਵਿੱਚੋਂ <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ਨੂੰ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਸ ਲੜੀ ਅਤੇ ਹੋਰਨਾਂ ਲੜੀਆਂ ਦੇ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ਐਪੀਸੋਡ ਨੂੰ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗਾਂ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਇਸ ਲੜੀ ਅਤੇ ਹੋਰਨਾਂ ਲੜੀਆਂ ਦੇ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ਐਪੀਸੋਡਾਂ ਨੂੰ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਹੋਰਨਾਂ ਲੜੀਆਂ ਦੇ 1 ਐਪੀਸੋਡ ਦੀ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡਿੰਗ ਨਹੀਂ ਕੀਤੀ ਜਾਵੇਗੀ।</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗਾਂ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਹੋਰਨਾਂ ਲੜੀਆਂ ਦੇ 1 ਐਪੀਸੋਡ ਦੀ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡਿੰਗ ਨਹੀਂ ਕੀਤੀ ਜਾਵੇਗੀ।</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਹੋਰਨਾਂ ਲੜੀਆਂ ਦੇ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ਐਪੀਸੋਡ ਨੂੰ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</item>
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> ਲਈ <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ਰਿਕਾਰਡਿੰਗਾਂ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕੀਤਾ ਗਿਆ ਹੈ। ਹੋਰਨਾਂ ਲੜੀਆਂ ਦੇ <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ਐਪੀਸੋਡਾਂ ਨੂੰ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।</item>
+    </plurals>
+    <string name="dvr_program_not_found" msgid="3282879532038010202">"ਰਿਕਾਰਡ ਕੀਤਾ ਪ੍ਰੋਗਰਾਮ ਨਹੀਂ ਲੱਭਿਆ।"</string>
+    <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"ਸਬੰਧਿਤ ਰਿਕਾਰਡਿੰਗਾਂ"</string>
+    <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
+      <item quantity="one">%1$d ਰਿਕਾਰਡਿੰਗ</item>
+      <item quantity="other">%1$d ਰਿਕਾਰਡਿੰਗਾਂ</item>
+    </plurals>
+    <string name="dvr_schedules_information_separator" msgid="1669116853379998479">" / "</string>
+    <string name="dvr_schedules_deletion_info" msgid="2837586459900271031">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ਨੂੰ ਰਿਕਾਰਡਿੰਗ ਦੇ ਨਿਯਤ ਸਮੇਂ ਤੋਂ ਹਟਾਇਆ ਗਿਆ।"</string>
+    <string name="dvr_schedules_tuner_conflict_will_be_partially_recorded" msgid="5280490298546908729">"ਟਿਊਨਰ ਦੇ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਅਧੂਰਾ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="dvr_schedules_tuner_conflict_will_not_be_recorded_info" msgid="5065400564003201095">"ਟਿਊਨਰ ਦੇ ਵਿਵਾਦਾਂ ਦੇ ਕਾਰਨ ਰਿਕਾਰਡ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।"</string>
+    <string name="dvr_schedules_empty_state" msgid="1291529283469462741">"ਹਾਲੇ ਕਾਰਜ-ਕ੍ਰਮ \'ਤੇ ਕੋਈ ਰਿਕਾਰਡਿੰਗਾਂ ਨਹੀਂ ਹਨ।\nਤੁਸੀਂ ਪ੍ਰੋਗਰਾਮ ਗਾਈਡ ਵਿੱਚੋਂ ਰਿਕਾਰਡਿੰਗ ਦਾ ਸਮਾਂ ਨਿਯਤ ਕਰ ਸਕਦੇ ਹੋ।"</string>
+    <plurals name="dvr_series_schedules_header_description" formatted="false" msgid="9077188267856194114">
+      <item quantity="one">%1$d ਰਿਕਾਰਡਿੰਗ ਵਿਵਾਦ</item>
+      <item quantity="other">%1$d ਰਿਕਾਰਡਿੰਗ ਵਿਵਾਦ</item>
+    </plurals>
+    <string name="dvr_series_schedules_settings" msgid="4868501926847903985">"ਲੜੀ ਦੀਆਂ ਸੈਟਿੰਗਾਂ"</string>
+    <string name="dvr_series_schedules_start" msgid="8458768834047133835">"ਲੜੀ ਦੀ ਰਿਕਾਰਡਿੰਗ ਸ਼ੁਰੂ ਕਰੋ"</string>
+    <string name="dvr_series_schedules_stop" msgid="3427479298317584961">"ਲੜੀ ਦੀ ਰਿਕਾਰਡਿੰਗ ਬੰਦ ਕਰੋ"</string>
+    <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"ਕੀ ਲੜੀ ਦੀ ਰਿਕਾਰਡਿੰਗ ਬੰਦ ਕਰਨੀ ਹੈ?"</string>
+    <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"ਰਿਕਾਰਡ ਕੀਤੇ ਐਪੀਸੋਡ DVR ਲਾਇਬਰੇਰੀ ਵਿੱਚ ਉਪਲਬਧ ਰਹਿਣਗੇ।"</string>
+    <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"ਬੰਦ ਕਰੋ"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ਕੋਈ ਵੀ ਐਪੀਸੋਡਾਂ ਦਾ ਹੁਣ ਪ੍ਰਸਾਰਨ ਨਹੀਂ ਹੋ ਰਿਹਾ ਹੈ।"</string>
+    <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"ਕੋਈ ਐਪੀਸੋਡ ਉਪਲਬਧ ਨਹੀਂ ਹਨ।\nਉਪਲਬਧ ਹੋਣ \'ਤੇ ਉਹਨਾਂ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਵੇਗਾ।"</string>
+    <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
+      <item quantity="one">(%1$d ਮਿੰਟ)</item>
+      <item quantity="other">(%1$d ਮਿੰਟ)</item>
+    </plurals>
+    <string name="dvr_date_today" msgid="7691050705354303471">"ਅੱਜ"</string>
+    <string name="dvr_date_tomorrow" msgid="4136735681186981844">"ਭਲਕੇ"</string>
+    <string name="dvr_date_yesterday" msgid="2127672919053118239">"ਕੱਲ੍ਹ"</string>
+    <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ਅੱਜ"</string>
+    <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ਭਲਕੇ"</string>
+    <string name="program_guide_critic_score" msgid="340530743913585150">"ਸਕੋਰ"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"ਰਿਕਾਰਡ ਕੀਤੇ ਪ੍ਰੋਗਰਾਮ"</string>
+</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 1e86cb7..3db5beb 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Sterowanie odtwarzaniem"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Ostatnie kanały"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanały"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opcje TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opcje PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Elementy sterujące Play są niedostępne dla tego kanału"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Odtwórz lub wstrzymaj"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Przewiń do przodu"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Napisy"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Tryb wyświetl."</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Włączony"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Wyłączony"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Wiele kan. audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Więcej kanałów"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Ustawienia"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Źródło"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Przełącz"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Włączone"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Wyłączone"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Dźwięk"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Główne okno"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Okno PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Układ"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Prawy dolny róg"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Prawy górny róg"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Lewy górny róg"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Lewy dolny róg"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Obok siebie"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Rozmiar"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Duży"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Mały"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Źródło sygnału"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Brak informacji o programach"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Brak informacji"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Kanał zablokowany"</string>
-    <string name="default_language" msgid="4122326459624337928">"Nieznany język"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Nieznany język"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Napisy: %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Napisy"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Wył."</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Dostosuj format"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Grupuj według"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Ten program jest zablokowany"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ten program nie ma oceny"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Ten program ma ocenę <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Wejście nie obsługuje automatycznego skanowania"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Nie można rozpocząć automatycznego skanowania dla „<xliff:g id="TV_INPUT">%s</xliff:g>”"</string>
@@ -94,7 +76,6 @@
       <item quantity="one">Dodano %1$d kanał</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Nie dodano kanałów"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Kontr. rodziciel."</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Wł."</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Wył."</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Inne kraje"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Brak"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Brak"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Bez oceny"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokuj programy bez oceny"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Brak"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Duże ograniczenia"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Średnie ograniczenia"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Wpisz kod PIN, by oglądać ten kanał"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Wpisz kod PIN, by oglądać ten program"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Ten program ma ocenę <xliff:g id="RATING">%1$s</xliff:g>. Aby go obejrzeć, podaj kod PIN."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ten program nie ma oceny. Aby go obejrzeć, podaj kod PIN"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Wpisz kod PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Aby ustawić kontrolę rodzicielską, utwórz PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Wpisz nowy PIN"</string>
@@ -139,22 +123,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Nieprawidłowy PIN. Spróbuj ponownie"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Spróbuj ponownie. Niezgodny kod PIN"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Wpisz kod pocztowy."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Aplikacja Telewizja online będzie używać kodu pocztowego, by udostępniać kompletny przewodnik po programach telewizyjnych."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Wpisz kod pocztowy"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Nieprawidłowy kod pocztowy"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Ustawienia"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Dostosuj listę kanałów"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Wybierz kanały do przewodnika TV"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Źródła kanałów"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Dostępne są nowe kanały"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Kontrola rodzicielska"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Przesunięcie w czasie"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Nagrywaj podczas oglądania, by móc wstrzymywać i przewijać programy na żywo.\nOstrzeżenie: funkcja ta intensywnie korzysta z pamięci wewnętrznej, co może skrócić jej żywotność."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licencje open source"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licencje open source"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Prześlij opinię"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Wersja"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Aby oglądać ten kanał, naciśnij Prawo i wpisz kod PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Aby oglądać ten program, naciśnij Prawo i wpisz kod PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ten program nie ma oceny.\nAby go obejrzeć, naciśnij przycisk W prawo i podaj kod PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Ten program ma ocenę <xliff:g id="RATING">%1$s</xliff:g>.\nAby go oglądać, naciśnij Prawo i wpisz kod PIN"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Aby oglądać ten kanał, użyj standardowej aplikacji Telewizja na żywo."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Aby obejrzeć ten program, użyj standardowej aplikacji Telewizja na żywo."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ten program nie ma oceny.\nAby go obejrzeć, użyj domyślnej aplikacji do obsługi telewizji na żywo."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Ten program ma ocenę <xliff:g id="RATING">%1$s</xliff:g>.\nAby go obejrzeć, użyj standardowej aplikacji Telewizja na żywo."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Program jest zablokowany"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ten program nie ma oceny"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Ten program ma ocenę <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Tylko dźwięk"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Słaby sygnał"</string>
@@ -189,8 +182,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Naciśnij SELECT"</b>", by otworzyć menu TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nie znaleziono wejścia TV"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Nie można znaleźć wejścia TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Tryb PIP nie jest obsługiwany"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Brak sygnału wejściowego do wyświetlenia w trybie PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Nieodpowiedni typ tunera. Uruchom aplikację Telewizja online na jego wejściu TV."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Strojenie nie powiodło się"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Nie znaleziono aplikacji do obsługi tego działania."</string>
@@ -199,7 +190,7 @@
     <string name="msg_back_key_guide" msgid="7404682718828721924">"Klawisz BACK steruje podłączonym urządzeniem. Naciśnij przycisk HOME, by wyjść."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Aby odczytywać programy telewizyjne, Telewizja online potrzebuje uprawnień."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Skonfiguruj źródła"</string>
-    <string name="setup_sources_description" msgid="5695518946225445202">"Telewizja online to połączenie tradycyjnych kanałów TV i przesyłanych strumieniowo przez aplikacje.\n\nAby rozpocząć, skonfiguruj zainstalowane źródła kanałów. Możesz też przejrzeć Sklep Google Play, by znaleźć więcej aplikacji, które oferują dostęp do telewizji online."</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"Telewizja online to połączenie tradycyjnych kanałów TV i przesyłanych strumieniowo przez aplikacje.\n\nAby rozpocząć, skonfiguruj zainstalowane źródła kanałów. Możesz też przejrzeć Sklep Google Play, by znaleźć więcej aplikacji, które oferują dostęp do telewizji online."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Nagrywanie i harmonogramy"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minut"</string>
     <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 minut"</string>
@@ -244,6 +235,8 @@
       <item quantity="other">%1$d zaplanowanego nagrania</item>
       <item quantity="one">%1$d zaplanowane nagranie</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Anuluj nagrywanie"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Zatrzymaj nagrywanie"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Obejrzyj"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Odtwórz od początku"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Wznów odtwarzanie"</string>
@@ -278,9 +271,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Jeśli wybierzesz za dużo programów do nagrania w tym samym czasie, nagrane zostaną tylko te o wyższych priorytetach."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Zapisz"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Nagrania jednorazowe mają najwyższy priorytet"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Anuluj"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Anuluj"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Zapomnij"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Zatrzymaj"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Pokaż harmonogram nagrywania"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Tylko ten program"</string>
@@ -290,25 +280,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Nagraj to w zamian"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Anuluj to nagrywanie"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Obejrzyj teraz"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Usuń nagrania…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Można nagrać"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Zaplanowano nagrywanie"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Konflikt nagrywania"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Nagrywam"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Nie udało się nagrać"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Odczytuję programy, by utworzyć harmonogram nagrywania"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Odczytuję programy"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Odczytuję programy"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Zobacz ostatnie nagrania"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Nagranie <xliff:g id="PROGRAMNAME">%1$s</xliff:g> jest niepełne."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Nagrania <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> i <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> są niepełne."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Nagrania <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> i <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> są niepełne."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Nie udało się dokończyć nagrania <xliff:g id="PROGRAMNAME">%1$s</xliff:g> z powodu braku miejsca."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Nie udało się dokończyć nagrań <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> i <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> z powodu braku miejsca."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Nie udało się dokończyć nagrań <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> i <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> z powodu braku miejsca."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Nagrywarka DVR potrzebuje więcej miejsca"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Dzięki funkcji nagrywarki DVR możesz nagrywać programy, ale obecnie na urządzeniu jest za mało miejsca, by można było z niej korzystać. Podłącz dysk zewnętrzny o pojemności co najmniej <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB i postępuj zgodnie z instrukcjami, by sformatować go jako pamięć urządzenia."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Dzięki funkcji nagrywarki DVR możesz nagrywać programy, ale obecnie na urządzeniu jest za mało miejsca, by można było z niej korzystać. Podłącz dysk zewnętrzny o pojemności co najmniej <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB i postępuj zgodnie z instrukcjami, by sformatować go jako pamięć urządzenia."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Za mało miejsca"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Nie można nagrać tego programu, bo brakuje miejsca. Usuń któreś z wcześniejszych nagrań."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Brak dostępu do pamięci"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Brak dostępu do części pamięci wykorzystywanej przez DVR. Podłącz dysk zewnętrzny, którego używasz, zanim włączysz DVR ponownie. Jeśli nie masz już tego dysku zewnętrznego, możesz go zapomnieć."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Zapomnieć pamięć nagrywarki?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Wszystkie zapisane treści i zaplanowane nagrania zostaną utracone."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Zatrzymać nagrywanie?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Nagrana treść zostanie zapisana."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Nagrywanie programu „<xliff:g id="PROGRAMNAME">%1$s</xliff:g>” zostanie zatrzymane, bo jest w konflikcie z tym programem. Nagrane treści zostaną zachowane."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Nagrywanie zostało zaplanowane, ale wystąpiły konflikty"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Zaczęło się nagrywanie, ale występują konflikty"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Program <xliff:g id="PROGRAMNAME">%1$s</xliff:g> zostanie nagrany."</string>
@@ -328,17 +321,39 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Nagrywanie tego samego programu zostało już zaplanowane na <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Już nagrany"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Ten program został już nagrany. Jest dostępny w bibliotece nagrywarki DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Zaplanowano nagrywanie serialu"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="few">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="many">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrań serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nagranie serialu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="few">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z powodu pokrywających się harmonogramów nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> odcinków.</item>
+      <item quantity="many">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrań serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z powodu pokrywających się harmonogramów nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> odcinków.</item>
+      <item quantity="other">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Z powodu pokrywających się harmonogramów nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> odcinków.</item>
+      <item quantity="one">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nagranie serialu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Z powodu pokrywających się harmonogramów nie uda się nagrać tego odcinka.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="few">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z powodu pokrywających się harmonogramów nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> odcinków tego i innych seriali.</item>
+      <item quantity="many">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nagrań serialu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z powodu pokrywających się harmonogramów nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> odcinków tego i innych seriali.</item>
+      <item quantity="other">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Z powodu pokrywających się harmonogramów nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> odcinków tego i innych seriali.</item>
+      <item quantity="one">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nagranie serialu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Z powodu pokrywających się harmonogramów nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> odcinków tego i innych seriali.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="few">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Przez to nie uda się nagrać 1 odcinka innego serialu.</item>
+      <item quantity="many">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrań serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Przez to nie uda się nagrać 1 odcinka innego serialu.</item>
+      <item quantity="other">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Przez to nie uda się nagrać 1 odcinka innego serialu.</item>
+      <item quantity="one">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nagranie serialu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Przez to nie uda się nagrać 1 odcinka innego serialu.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="few">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Przez to nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> odcinków innych seriali.</item>
+      <item quantity="many">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nagrań serialu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Przez to nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> odcinków innych seriali.</item>
+      <item quantity="other">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> nagrania serialu <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Przez to nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> odcinków innych seriali.</item>
+      <item quantity="one">Zaplanowano <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> nagranie serialu <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Przez to nie uda się nagrać <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> odcinków innych seriali.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Nie znaleziono nagranego programu."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Powiązane nagrania"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Brak opisu programu)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="few">%1$d nagrania</item>
       <item quantity="many">%1$d nagrań</item>
@@ -362,6 +377,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Zatrzymać nagrywanie cykliczne?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Nagrane odcinki będą dostępne w bibliotece nagrywarki DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Zatrzymaj"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"W tej chwili nie są nadawane żadne odcinki."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Brak dostępnych odcinków.\nZostaną one nagrane, gdy będą dostępne."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="few">(%1$d minuty)</item>
@@ -375,4 +391,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Dzisiaj, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Jutro, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Ocena"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Nagrane programy"</string>
 </resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 45fa4e2..d1d3d09 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"estéreo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Controlos de reprodução"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Canais recentes"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Canais"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opções de TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opções de PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Controlos de reprodução indisponíveis para este canal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Reproduzir ou colocar em pausa"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avançar"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Legendas"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Modo de apres."</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Ativado"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Desativado"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multiáudio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Obter mais canais"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Definições"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Fonte"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Alternar"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Ativado"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Desativado"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Som"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principal"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Janela de PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Esquema"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Canto inf. dir."</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Canto sup. dir."</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Canto sup. esq."</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Canto inf. esq."</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Lado a lado"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Tamanho"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Grande"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Pequeno"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Fonte de entrada"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/cabo)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Sem informação de programação"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Sem informações"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Canal bloqueado"</string>
-    <string name="default_language" msgid="4122326459624337928">"Idioma desconhecido"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Idioma desconhecido"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Legendas %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Legendas"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Desativado"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Person. a formatação"</string>
@@ -83,16 +64,16 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Agrupar por"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Este programa está bloqueado"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Este programa não tem classificação."</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Este programa tem a classificação <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"A entrada não suporta procura automática"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Não é possível iniciar a verificação automática para \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
     <string name="msg_unable_to_start_system_captioning_settings" msgid="705242616044165668">"Não é possível iniciar as preferências do sistema para as legendas."</string>
     <plurals name="msg_channel_added" formatted="false" msgid="5301526166755938705">
-      <item quantity="other">%1$d canais adicionados</item>
       <item quantity="one">%1$d canal adicionado</item>
+      <item quantity="other">%1$d canais adicionados</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Nenhum canal adicionado"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sintonizador"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Controlo parental"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Ativado"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Desativado"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Outros países"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Nenhum"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Nenhum"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Sem classificação"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloquear programas s/ classif."</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Nenhum"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restrições elevadas"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restrições médias"</string>
@@ -124,48 +107,58 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Introduzir o PIN para ver este canal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Introduzir o PIN para ver este programa"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Este programa tem a classificação <xliff:g id="RATING">%1$s</xliff:g>. Introduza o PIN para ver este programa"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Este programa não tem classificação. Introduza o PIN para ver este programa."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Introduzir o PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Para definir os controlos parentais, crie um PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Introduzir o novo PIN"</string>
     <string name="pin_enter_again" msgid="2618999754723090427">"Confirmar o PIN"</string>
     <string name="pin_enter_old_pin" msgid="4588282612931041919">"Introduzir o PIN atual"</string>
     <plurals name="pin_enter_countdown" formatted="false" msgid="3415233538538544309">
-      <item quantity="other">Introduziu 5 vezes o PIN incorreto.\nTente novamente dentro de <xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> segundos.</item>
       <item quantity="one">Introduziu 5 vezes o PIN incorreto.\nTente novamente dentro de <xliff:g id="REMAINING_SECONDS_0">%1$d</xliff:g> segundo.</item>
+      <item quantity="other">Introduziu 5 vezes o PIN incorreto.\nTente novamente dentro de <xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> segundos.</item>
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Esse PIN estava errado. Tente novamente."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Tente novamente, o PIN não corresponde"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Introduza o seu código postal."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"A aplicação Canais em Direto utiliza o código postal para disponibilizar um guia de programação completo para os canais de TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Introduza o seu código postal"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Código postal inválido"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Definições"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalizar lista de canais"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Escolher canais para o guia de programação"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Fontes dos canais"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Novos canais disponíveis"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Controlo parental"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Controlo da reprodução"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Grave enquanto está a ver para poder colocar em pausa ou recuar programas em direto.\nAviso: isto pode reduzir a vida útil da memória de armazenamento interno devido à utilização intensiva da mesma."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licenças de código aberto"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licenças de código aberto"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Enviar comentários"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versão"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Para ver este canal, prima Direito e introduza o PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Para ver este programa, prima Direito e introduza o PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Este programa não tem classificação.\nPara ver este programa, prima Para a direita e introduza o PIN."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Este programa tem a classificação <xliff:g id="RATING">%1$s</xliff:g>.\nPara ver este programa, prima Direito e introduza o PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Para ver este canal, utilize a aplicação TV em direto predefinida."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Para ver este programa, utilize a aplicação TV em direto predefinida."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Este programa não tem classificação.\nPara ver este programa, utilize a aplicação de TV em direto predefinida."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Este programa tem a classificação <xliff:g id="RATING">%1$s</xliff:g>.\nPara o ver, utilize a aplicação TV em direto predefinida."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"O programa está bloqueado"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Este programa não tem classificação."</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Este programa tem a classificação <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Apenas áudio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Sinal fraco"</string>
     <string name="tvview_msg_no_internet_connection" msgid="7655994401188888231">"Sem ligação à Internet"</string>
     <plurals name="tvview_msg_input_no_resource" formatted="false" msgid="8581894855153658823">
-      <item quantity="other">Não é possível reproduzir este canal até à(s) <xliff:g id="END_TIME_1">%1$s</xliff:g> porque estão a ser gravados outros canais. \n\nPrima para a direita para ajustar o horário de gravação.</item>
       <item quantity="one">Não é possível reproduzir este canal até à(s) <xliff:g id="END_TIME_0">%1$s</xliff:g> porque está a ser gravado outro canal. \n\nPrima para a direita para ajustar o horário de gravação.</item>
+      <item quantity="other">Não é possível reproduzir este canal até à(s) <xliff:g id="END_TIME_1">%1$s</xliff:g> porque estão a ser gravados outros canais. \n\nPrima para a direita para ajustar o horário de gravação.</item>
     </plurals>
     <string name="channel_banner_no_title" msgid="8660301979190693176">"Sem título"</string>
     <string name="channel_banner_locked_channel_title" msgid="2006564967318945980">"Canal bloqueado"</string>
     <string name="setup_category_new" msgid="2899355289563443627">"Nova"</string>
     <string name="setup_category_done" msgid="4750902502852212319">"Fontes"</string>
     <plurals name="setup_input_channels" formatted="false" msgid="1695941684075602971">
-      <item quantity="other">%1$d canais</item>
       <item quantity="one">%1$d canal</item>
+      <item quantity="other">%1$d canais</item>
     </plurals>
     <string name="setup_input_no_channels" msgid="1669327912393163331">"Nenhum canal disponível"</string>
     <string name="setup_input_new" msgid="3337725672277046798">"Nova"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Prima SELECT"</b>" para aceder ao menu da TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nenhuma entrada de TV encontrada"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Não é possível localizar a entrada de TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Não é suportada a opção PIP"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Nenhuma entrada disponível para apresentar com PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tipo de sintonizador inadequado. Inicie a aplicação Canais em direito para a entrada de TV do tipo de sintonizador."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Falha ao sintonizar"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Não foram encontradas aplicações para executar esta ação."</string>
@@ -207,25 +198,27 @@
     <string name="dvr_msg_current_program_scheduled" msgid="2505247201782991463">"A gravar <xliff:g id="PROGRAMNAME">%1$s</xliff:g> desde agora até às <xliff:g id="ENDTIME">%2$s</xliff:g>…"</string>
     <string name="dvr_full_schedule_card_view_title" msgid="7198521806965950089">"Agenda completa"</string>
     <plurals name="dvr_full_schedule_card_view_content" formatted="false" msgid="790788122541080768">
-      <item quantity="other">Próximos %1$d dias</item>
       <item quantity="one">Próximo dia</item>
+      <item quantity="other">Próximos %1$d dias</item>
     </plurals>
     <plurals name="dvr_program_duration" formatted="false" msgid="6742119148312354741">
-      <item quantity="other">%1$d minutos</item>
       <item quantity="one">%1$d minuto</item>
+      <item quantity="other">%1$d minutos</item>
     </plurals>
     <plurals name="dvr_count_new_recordings" formatted="false" msgid="3569310208305402815">
-      <item quantity="other">%1$d novas gravações</item>
       <item quantity="one">%1$d nova gravação</item>
+      <item quantity="other">%1$d novas gravações</item>
     </plurals>
     <plurals name="dvr_count_recordings" formatted="false" msgid="7417379223468131391">
-      <item quantity="other">%1$d gravações</item>
       <item quantity="one">%1$d gravação</item>
+      <item quantity="other">%1$d gravações</item>
     </plurals>
     <plurals name="dvr_count_scheduled_recordings" formatted="false" msgid="1650330290765214511">
-      <item quantity="other">%1$d gravações agendadas</item>
       <item quantity="one">%1$d gravação agendada</item>
+      <item quantity="other">%1$d gravações agendadas</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancelar gravação"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Parar gravação"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Ver"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Reproduzir do início"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Retomar a reprodução"</string>
@@ -245,8 +238,8 @@
     <string name="dvr_series_watched_info_seconds" msgid="2667537184197566662">"<xliff:g id="WATCHED">%1$d</xliff:g> de <xliff:g id="DURATION">%2$d</xliff:g> segundos vistos"</string>
     <string name="dvr_series_never_watched" msgid="6086008065876122655">"Nunca vistas"</string>
     <plurals name="dvr_msg_episodes_deleted" formatted="false" msgid="5627112959798353905">
-      <item quantity="other">%1$d de %2$d episódios eliminados</item>
       <item quantity="one">%1$d de %2$d episódio eliminado</item>
+      <item quantity="other">%1$d de %2$d episódios eliminados</item>
     </plurals>
     <string name="dvr_series_settings_priority" msgid="5836437092774185710">"Prioridade"</string>
     <string name="dvr_series_settings_priority_highest" msgid="1072006447796648382">"Mais alta"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Quando existem demasiados programas para serem gravados em simultâneo, apenas são gravados os programas com as prioridades mais altas."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Guardar"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"As gravações únicas têm a prioridade mais alta"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancelar"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancelar"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Esquecer"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Parar"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Ver horários de gravação"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Este programa único"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Gravar antes este"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancelar esta gravação"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Ver agora"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Eliminar gravações"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Gravável"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Gravação agendada"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Conflito de gravação"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"A gravar"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Falha na gravação"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"A ler os programas para criar horários de gravação…"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"A ler os programas…"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"A ler os programas…"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Ver gravações recentes"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"A gravação de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> está incompleta."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"As gravações de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> e <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> estão incompletas."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"As gravações de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> e <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> estão incompletas."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"A gravação de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> não foi concluída devido a armazenamento insuficiente."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"As gravações de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> e <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> não foram concluídas devido a armazenamento insuficiente."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"As gravações de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> e <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> não foram concluídas devido a armazenamento insuficiente."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"O DVR necessita de mais armazenamento"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Pode gravar programas com o DVR. Contudo, não existe neste momento armazenamento suficiente no dispositivo para que o DVR funcione. Ligue uma unidade externa que tenha, pelo menos, <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB e siga os passos para a formatar como armazenamento do dispositivo."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Pode gravar programas com o DVR. Contudo, não existe neste momento armazenamento suficiente no dispositivo para que o DVR funcione. Ligue uma unidade externa que tenha, pelo menos, <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB e siga os passos para a formatar como armazenamento do dispositivo."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Sem armazenamento suficiente"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Este programa não será gravado porque não existe armazenamento suficiente. Experimente eliminar algumas gravações existentes."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Armazenamento em falta"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Algum do armazenamento utilizado pelo DVR está em falta. Ligue a unidade externa que utilizou anteriormente para reativar o DVR. Em alternativa, pode optar por esquecer o armazenamento se este já não estiver disponível."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Pretende esquecer o armazenamento?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Todos os seus conteúdos e agendamentos gravados serão perdidos."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Pretende parar a gravação?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"O conteúdo gravado será guardado."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"A gravação de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> será interrompida devido a conflitos com este programa. O conteúdo gravado será guardado."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Gravação agendada, mas com conflitos"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"A gravação foi iniciada, mas tem conflitos"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"O programa <xliff:g id="PROGRAMNAME">%1$s</xliff:g> será gravado."</string>
@@ -297,8 +290,8 @@
     <string name="dvr_program_conflict_dialog_description_2" msgid="5648524408147235696">"Algumas partes de <xliff:g id="CONFLICTPROGRAMNAME_1">%1$s</xliff:g> e de <xliff:g id="CONFLICTPROGRAMNAME_2">%2$s</xliff:g> não serão gravadas."</string>
     <string name="dvr_program_conflict_dialog_description_3" msgid="6879199850098595108">"Algumas partes de <xliff:g id="CONFLICTPROGRAMNAME_1">%1$s</xliff:g>, de <xliff:g id="CONFLICTPROGRAMNAME_2">%2$s</xliff:g> e de mais um horário não serão gravadas."</string>
     <plurals name="dvr_program_conflict_dialog_description_many" formatted="false" msgid="1008340710252647947">
-      <item quantity="other">Algumas partes de <xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, de <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> e de mais %3$d horários não serão gravadas.</item>
       <item quantity="one">Algumas partes de <xliff:g id="CONFLICTPROGRAMNAME_1_0">%1$s</xliff:g>, de <xliff:g id="CONFLICTPROGRAMNAME_2_1">%2$s</xliff:g> e de mais %3$d horário não serão gravadas.</item>
+      <item quantity="other">Algumas partes de <xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, de <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> e de mais %3$d horários não serão gravadas.</item>
     </plurals>
     <string name="dvr_schedule_dialog_title" msgid="5235629824986156058">"O que gostaria de gravar?"</string>
     <string name="dvr_channel_record_duration_dialog_title" msgid="4601361040431047918">"Durante quanto tempo pretende gravar?"</string>
@@ -306,20 +299,32 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"O mesmo programa já foi agendado para ser gravado às <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Já gravado"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Este programa já foi gravado. Está disponível na biblioteca do DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Gravação da série agendada"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one">Foi agendada <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravação para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravações para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one">Foi agendada <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravação para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Esta não será gravada devido a conflitos.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravações para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> destas não serão gravadas devido a conflitos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one">Foi agendada <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravação para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episódios desta e de outras séries não serão gravados devido a conflitos.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> gravações para <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episódios desta e de outras séries não serão gravados devido a conflitos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one">Foi agendada <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravação para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Não será gravado 1 episódio de outra série devido a conflitos.</item>
+      <item quantity="other">Foram agendadas <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravações para <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Não será gravado 1 episódio de outra série devido a conflitos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one">Foi agendada <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> gravação para <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Não serão gravados <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episódios de outras séries devido a conflitos.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> gravações para <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Não serão gravados <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episódios de outras séries devido a conflitos.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Programa gravado não encontrado."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Gravações relacionadas"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Sem descrição do programa)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
-      <item quantity="other">%1$d gravações</item>
       <item quantity="one">%1$d gravação</item>
+      <item quantity="other">%1$d gravações</item>
     </plurals>
     <string name="dvr_schedules_information_separator" msgid="1669116853379998479">" / "</string>
     <string name="dvr_schedules_deletion_info" msgid="2837586459900271031">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> removido da agenda de gravação"</string>
@@ -327,8 +332,8 @@
     <string name="dvr_schedules_tuner_conflict_will_not_be_recorded_info" msgid="5065400564003201095">"Não será gravado devido a conflitos de sintonizador."</string>
     <string name="dvr_schedules_empty_state" msgid="1291529283469462741">"Ainda não existem gravações agendadas.\nPode agendar a gravação a partir do guia de programação."</string>
     <plurals name="dvr_series_schedules_header_description" formatted="false" msgid="9077188267856194114">
-      <item quantity="other">%1$d conflitos de gravação</item>
       <item quantity="one">%1$d conflito de gravação</item>
+      <item quantity="other">%1$d conflitos de gravação</item>
     </plurals>
     <string name="dvr_series_schedules_settings" msgid="4868501926847903985">"Definições de séries"</string>
     <string name="dvr_series_schedules_start" msgid="8458768834047133835">"Iniciar gravação da série"</string>
@@ -336,10 +341,11 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Pretende parar a gravação da série?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Os episódios gravados ficam disponíveis na biblioteca do DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Parar"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Não estão a ser transmitidos episódios em direto."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Não existem episódios disponíveis.\nVão ser gravados assim que estiverem disponíveis."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
-      <item quantity="other">(%1$d minutos)</item>
       <item quantity="one">(%1$d minuto) </item>
+      <item quantity="other">(%1$d minutos)</item>
     </plurals>
     <string name="dvr_date_today" msgid="7691050705354303471">"Hoje"</string>
     <string name="dvr_date_tomorrow" msgid="4136735681186981844">"Amanhã"</string>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> de hoje"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> de amanhã"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Pontuação"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programas gravados"</string>
 </resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 9c22a58..9a8abe2 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"estéreo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Controles de reprodução"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Canais recentes"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Canais"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opções da TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opções de PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Controles de reprodução indisponíveis para este canal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Reproduzir ou pausar"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Avançar"</string>
@@ -33,47 +32,29 @@
     <string name="channels_item_setup" msgid="6557412175737379022">"Novos canais disponíveis"</string>
     <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"Abrir <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Closed captions"</string>
-    <string name="options_item_display_mode" msgid="7989243076748680140">"Modo de exibiç."</string>
+    <string name="options_item_display_mode" msgid="7989243076748680140">"Modo de exibição"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Ativado"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Desativado"</string>
-    <string name="options_item_multi_audio" msgid="5118851311937896923">"Múltip. áudios"</string>
-    <string name="options_item_more_channels" msgid="971040969622943300">"Adquirir mais canais"</string>
-    <string name="options_item_settings" msgid="7623205838542400074">"Config."</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Origem"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Trocar"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Ativadas"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Desativadas"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Som"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principal"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Janela de PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Inferior direito"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Superior direito"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Superior esquerdo"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Inferior esquerdo"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Lado a lado"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Tamanho"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Grande"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Pequeno"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Origem da entrada"</string>
+    <string name="options_item_multi_audio" msgid="5118851311937896923">"Áudios múltiplos"</string>
+    <string name="options_item_more_channels" msgid="971040969622943300">"Mais canais"</string>
+    <string name="options_item_settings" msgid="7623205838542400074">"Configurações"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/a cabo)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Nenhuma informação sobre o programa"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Nenhuma informação"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Canal bloqueado"</string>
-    <string name="default_language" msgid="4122326459624337928">"Idioma desconhecido"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Idioma desconhecido"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Closed captions %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Closed captions"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Desativado"</string>
-    <string name="closed_caption_system_settings" msgid="1856974607743827178">"Person. formatação"</string>
-    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Definir preferências gerais do sistema para closed captions"</string>
+    <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personalizar formatação"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Defina as preferências gerais do sistema para closed captions"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Modo de exibição"</string>
-    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Múltiplos áudios"</string>
+    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Áudios múltiplos"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"mono"</string>
     <string name="multi_audio_channel_stereo" msgid="3758995659214256587">"estéreo"</string>
     <string name="multi_audio_channel_surround_6" msgid="6066304966228963942">"Surround 5.1"</string>
     <string name="multi_audio_channel_surround_8" msgid="2765140653768694313">"Surround 7.1"</string>
     <string name="multi_audio_channel_suffix" msgid="4443825738196093772">"%d canais"</string>
-    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"Pers. lista canais"</string>
+    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"Personalizar lista de canais"</string>
     <string name="edit_channels_item_select_group" msgid="4953000352257999703">"Selecionar grupo"</string>
     <string name="edit_channels_item_deselect_group" msgid="5092649099546997807">"Desmarcar grupo"</string>
     <string name="edit_channels_item_group_by" msgid="7794571851966798199">"Agrupar por"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"Padrão"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Agrupar por"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Este programa está bloqueado"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Este programa não tem classificação"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Este programa foi classificado como <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"A entrada não suporta verificação automática"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Não foi possível iniciar a verificação automática de \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d canais adicionados</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Nenhum canal adicionado"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sintonizador"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Contr. p/ os pais"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Ativado"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Desativado"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Outros países"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Nenhum"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Nenhum"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Sem classificação"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Bloquear programas sem classificação"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Nenhum"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restrições altas"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restrições médias"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Digite seu PIN para assistir a este canal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Digite seu PIN para assistir a este programa"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Este programa foi classificado como <xliff:g id="RATING">%1$s</xliff:g>. Digite seu PIN para assisti-lo"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Este programa não tem classificação. Digite seu PIN para assisti-lo"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Informe seu PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Para definir os controles para os pais, crie um PIN."</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Inserir novo PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"O PIN estava errado. Tente novamente."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Tente novamente, o PIN não corresponde"</string>
-    <string name="side_panel_title_settings" msgid="8244327316510918755">"Config."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Digite seu CEP."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"O app Canais ao vivo usará o CEP para fornecer um guia completo da programação para os canais de TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Digite seu CEP"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"CEP inválido"</string>
+    <string name="side_panel_title_settings" msgid="8244327316510918755">"Configurações"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalizar lista de canais"</string>
-    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Escolher canais para guia de programação"</string>
-    <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Fontes do canal"</string>
+    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Escolha canais para o guia de programação"</string>
+    <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Fontes de canais"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Novos canais disponíveis"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Controle dos pais"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Diferença de tempo"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Grave enquanto assiste para poder pausar ou retroceder programas ao vivo.\nAviso: isso pode diminuir a vida útil do armazenamento interno devido ao uso intenso do armazenamento."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licenças de código aberto"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licenças de código aberto"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Enviar feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versão"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Para assistir a este canal, pressione para a direita e digite o PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Para assistir a este programa, pressione para a direita e digite o PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Este programa não tem classificação.\nPressione o botão direito e digite seu PIN para assisti-lo"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Este programa foi classificado como <xliff:g id="RATING">%1$s</xliff:g>.\nPara assistir a este programa, pressione para a direita e digite o PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Para assistir este canal, use o app padrão de TV ao vivo."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Para assistir este programa, use o app padrão de TV ao vivo."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Este programa não tem classificação.\nUse o app padrão de TV ao vivo para assisti-lo."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Este programa foi classificado como <xliff:g id="RATING">%1$s</xliff:g>.\nPara assistir este programa, use o app padrão de TV ao vivo."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programa bloqueado"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Este programa não tem classificação"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Este programa foi classificado como <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Somente áudio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Sinal fraco"</string>
@@ -170,8 +163,8 @@
     <string name="setup_input_no_channels" msgid="1669327912393163331">"Nenhum canal disponível"</string>
     <string name="setup_input_new" msgid="3337725672277046798">"Novas"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Não configurada"</string>
-    <string name="setup_store_action_title" msgid="4083402039720973414">"Adquirir mais fontes"</string>
-    <string name="setup_store_action_description" msgid="6820482635042445297">"Procurar apps que ofereçam canais ao vivo"</string>
+    <string name="setup_store_action_title" msgid="4083402039720973414">"Adquira mais fontes"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Procure apps que ofereçam canais ao vivo"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"Novas fontes de canais disponíveis"</string>
     <string name="new_sources_description" msgid="749649005588426813">"Novas fontes de canais têm canais para oferecer.\nConfigure-as agora ou faça isso mais tarde nas configurações de fontes de canais."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Configurar agora"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Pressione \"SELECIONAR\""</b>" para acessar o menu da TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nenhuma entrada de TV encontrada"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Não foi possível encontrar a entrada de TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP não é suportado"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Não há entrada disponível que possa ser mostrada com PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tipo de sintonizador não adequado. Inicie o app \"Canais ao vivo\" para abrir o tipo de sintonizador para entrada de TV."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Falha na sintonia"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Nenhum app foi encontrado para executar esta ação."</string>
@@ -190,7 +181,7 @@
     <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"O vídeo está inesperadamente indisponível"</string>
     <string name="msg_back_key_guide" msgid="7404682718828721924">"A tecla VOLTAR é para dispositivos conectados. Pressione o botão INÍCIO para sair."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"O app \"Canais ao vivo\" precisa de permissão para ler a programação de TV."</string>
-    <string name="setup_sources_text" msgid="4988039637873759839">"Configurar suas fontes"</string>
+    <string name="setup_sources_text" msgid="4988039637873759839">"Configure suas fontes"</string>
     <string name="setup_sources_description" msgid="5695518946225445202">"Os canais ao vivo combinam a experiência dos canais de TV tradicionais com canais de streaming fornecidos por apps. \n\nComece configurando as fontes de canais já instaladas ou procure na Google Play Store mais apps que ofereçam canais ao vivo."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Gravações e programações"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minutos"</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d gravação programada</item>
       <item quantity="other">%1$d gravações programadas</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Cancelar gravação"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Interromper gravação"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Assistir"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Reproduzir do início"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Retomar reprodução"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Quando houver muitos programas a serem gravados ao mesmo tempo, apenas os com maior prioridade serão gravados."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Salvar"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Gravações únicas têm a maior prioridade"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Cancelar"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Cancelar"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Ignorar"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Parar"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Ver programação de gravação"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Este único programa"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Gravar este, e não o outro"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Cancelar esta gravação"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Assistir agora"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Excluir gravações…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Pode ser gravado"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Gravação programada"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Conflito de gravação"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Gravação"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Falha na gravação"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Lendo programas para criar programações de gravação"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Lendo programas"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Lendo programas"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Ver gravações recentes"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"A gravação de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> está incompleta."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"As gravações de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> e <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> estão incompletas."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"As gravações de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> e <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> estão incompletas."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"A gravação de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> não foi concluída devido à falta de espaço de armazenamento."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"As gravações de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> e <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> não foram concluídas devido à falta de espaço de armazenamento."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"As gravações de <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> e <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> não foram concluídas devido à falta de espaço de armazenamento."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"O DVR precisa de mais armazenamento"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Você poderá gravar programas com DVR. No entanto, não há espaço de armazenamento suficiente no seu dispositivo no momento para que o DVR funcione. Conecte um drive externo que tenha <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB ou mais e siga as etapas para formatá-lo como um armazenamento do dispositivo."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Você poderá gravar programas com DVR. No entanto, não há espaço de armazenamento suficiente no seu dispositivo no momento para que o DVR funcione. Conecte um drive externo que tenha <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB ou mais e siga as etapas para formatá-lo como um armazenamento do dispositivo."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Armazenamento insuficiente"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Este programa não será gravado porque não há espaço de armazenamento suficiente. Tente excluir algumas gravações já existentes."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Armazenamento ausente"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Alguns dos armazenamentos usados por DVR estão ausentes. Conecte o drive externo usado antes de reativar o DVR. Também é possível optar por esquecer o armazenamento se ele não estiver mais disponível."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Esquecer armazenamento?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Todo o conteúdo gravado e programações serão perdidos."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Interromper gravação?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"O conteúdo gravado será salvo."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"A gravação de <xliff:g id="PROGRAMNAME">%1$s</xliff:g> será interrompida porque ela tem um conflito com esse programa. O conteúdo gravado será salvo."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Gravação programada, mas há conflitos"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"A gravação começou, mas há conflitos"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"O programa <xliff:g id="PROGRAMNAME">%1$s</xliff:g> será gravado."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"A gravação do mesmo programa já foi programada para <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Já gravado"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Este programa já foi gravado. Ele está disponível na biblioteca de DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Gravação de série programada"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one">Foi programada <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravação de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other">Foram programadas <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravações de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one">Foi programada <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravação de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Ao todo, <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> delas não serão gravadas devido a conflitos.</item>
+      <item quantity="other">Foram programadas <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravações de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Ao todo, <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> delas não serão gravadas devido a conflitos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one">Foi programada <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> gravação de <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Ao todo, <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episódios dessa e de outras séries não serão gravados devido a conflitos.</item>
+      <item quantity="other">Foram programadas <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> gravações de <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Ao todo, <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episódios dessa e de outras séries não serão gravados devido a conflitos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one">Foi programada <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravação de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Ao todo, 1 episódio de outras séries não será gravado devido a conflitos.</item>
+      <item quantity="other">Foram programadas <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> gravações de <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Ao todo, 1 episódio de outras séries não será gravado devido a conflitos.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one">Foi programada <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> gravação de <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Ao todo, <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episódios de outras séries não serão gravados devido a conflitos.</item>
+      <item quantity="other">Foram programadas <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> gravações de <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Ao todo, <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episódios de outras séries não serão gravados devido a conflitos.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Programa gravado não encontrado."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Gravações relacionadas"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"Nenhuma descrição do programa"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d gravação</item>
       <item quantity="other">%1$d gravações</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Parar gravação da série?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Os episódios gravados permanecerão disponíveis na biblioteca de DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Parar"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Nenhum episódio está sendo transmitido no momento."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nenhum episódio disponível.\nOs episódios serão gravados quando estiverem disponíveis."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minuto)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> hoje"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> amanhã"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Pontuação"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programas gravados"</string>
 </resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index adc3b35..1fe9e1e 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Comenzi de redare"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Canale recente"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Canale"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opțiuni TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Opțiuni PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Comenzile de redare nu sunt disponibile pentru acest canal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Redați sau întrerupeți redarea"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Derulați rapid înainte"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Subtitrări"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Mod de afișare"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Activat"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Dezactivat"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Obțineți mai multe canale"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Setări"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Sursă"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Schimbați"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Activat"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Dezactivat"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Sunet"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Principală"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Fereastră PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Aspect"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Dreapta jos"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Dreapta sus"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Stânga sus"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Stânga jos"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Alăturat"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Dimensiuni"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Mare"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Mic"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Sursă de intrare"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenă/cablu)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Nu există informații despre program"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Nicio informație"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Canal blocat"</string>
-    <string name="default_language" msgid="4122326459624337928">"Limbă necunoscută"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Limbă necunoscută"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Subtitrări %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Subtitrări"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Dezactivat"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personaliz. format."</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Grupați după"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Acest program este blocat"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Acest program nu este evaluat"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Acest program este clasificat ca <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Intrarea nu acceptă scanarea automată"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Nu poate fi inițiată scanarea automată pentru „<xliff:g id="TV_INPUT">%s</xliff:g>”"</string>
@@ -93,7 +75,6 @@
       <item quantity="one">%1$d canal adăugat</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Niciun canal adăugat"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Control parental"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Activat"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Dezactivat"</string>
@@ -109,6 +90,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Alte țări"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Niciunul"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Niciunul"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Neevaluat"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blocați programele neevaluate"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Niciuna"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Restricții majore"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Restricții medii"</string>
@@ -125,6 +108,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Introduceți codul PIN pentru a viziona acest canal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Introduceți codul PIN pt. a viziona acest program"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Acest program este evaluat cu <xliff:g id="RATING">%1$s</xliff:g>. Pentru a viziona programul, introduceți codul PIN"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Acest program nu este evaluat. Introduceți codul PIN pentru a-l viziona."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Introduceți codul PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Pentru a seta controlul parental, creați un cod PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Introduceți un nou cod PIN"</string>
@@ -137,22 +121,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Codul PIN a fost greșit. Încercați din nou."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Încercați din nou. Codul PIN nu se potrivește."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Introduceți codul poștal"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Aplicația Canale live va folosi codul poștal pentru a vă oferi un ghid de programe complet pentru canalele TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Introduceți codul poștal"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Cod poștal nevalid"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Setări"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalizați lista de canale"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Alegeți canale pentru ghidul de programe"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Sursele canalelor"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Noi canale disponibile"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Control parental"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Decalare temporală"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Înregistrați în timpul vizionării, ca să puteți întrerupe sau derula înapoi programele live.\nAvertisment: astfel, se utilizează intensiv memoria internă și i se poate reduce durata de viață."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licențe open source"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licențe open source"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Trimiteți feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versiune"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Pentru a viziona acest canal, apăsați la dreapta și introduceți codul PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Pentru a viziona acest program, apăsați la dreapta și introduceți codul PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Acest program nu este evaluat.\nPentru a-l viziona, apăsați pe Drept și introduceți codul PIN."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Acest program este clasificat ca <xliff:g id="RATING">%1$s</xliff:g>.\nPentru a viziona acest program, apăsați pe săgeata spre dreapta și introduceți codul PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Pentru a viziona acest canal, folosiți aplicația prestabilită pentru programe TV live."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Pentru a viziona acest program, folosiți aplicația prestabilită pentru programe TV live."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Acest program nu este evaluat.\nPentru a-l viziona, utilizați aplicația prestabilită TV live."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Acest program este evaluat cu <xliff:g id="RATING">%1$s</xliff:g>.\nPentru a viziona acest program, folosiți aplicația prestabilită pentru programe TV live."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programul este blocat"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Acest program nu este evaluat"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Acest program este clasificat ca <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Numai conținut audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Semnal slab"</string>
@@ -185,8 +178,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Apăsați pe SELECTAȚI"</b>" pentru a accesa meniul TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nu s-a găsit nicio intrare TV"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Nu se poate găsi intrarea TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Funcția PIP nu este acceptată"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Nu există intrări disponibile pentru afișarea cu PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tipul tuner nu este corespunzător. Lansați aplicația Canale live pentru intrarea TV tip tuner."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Eroare la optimizare"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Nu s-a găsit o aplicație care să îndeplinească această acțiune."</string>
@@ -235,6 +226,8 @@
       <item quantity="other">%1$d de înregistrări programate</item>
       <item quantity="one">%1$d înregistrare programată</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Anulați înregistrarea"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Opriți înregistrarea"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Vizionați"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Redați de la început"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Reluați redarea"</string>
@@ -268,9 +261,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Când există prea multe programe de înregistrat în același timp, vor fi înregistrate numai cele cu priorități mai mari."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Salvați"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Înregistrările unice au cea mai mare prioritate"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Anulați"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Anulați"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Eliminați"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Opriți"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Vedeți programul de înregistrare"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Numai acest program"</string>
@@ -280,25 +270,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Înregistrați acest program"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Anulați această înregistrare"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Vedeți acum"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Ștergeți înregistrări…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Se poate înregistra"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Înregistrare programată"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Conflict privind înregistrarea"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Se înregistrează"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Nu s-a înregistrat"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Se citesc programele pentru crearea programărilor de înregistrare"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Se citesc programele"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Se citesc programele"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Vedeți înregistrările recente"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Înregistrarea pentru <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nu este finalizată."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Înregistrările pentru <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> și <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nu sunt finalizate."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Înregistrările pentru <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> și <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nu sunt finalizate."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Înregistrarea pentru <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nu s-a finalizat, din cauza spațiului de stocare insuficient."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Înregistrările pentru <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> și <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nu s-au finalizat, din cauza spațiului de stocare insuficient."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Înregistrările pentru <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> și <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nu s-au finalizat, din cauza spațiului de stocare insuficient."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR are nevoie de mai mult spațiu de stocare"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Veți putea înregistra programe folosind DVR. Cu toate acestea, momentan, pe dispozitiv nu există suficient spațiu de stocare ca să funcționeze DVR-ul. Conectați o unitate externă de cel puțin <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB și urmați pașii pentru a o formata ca stocare pe dispozitiv."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Veți putea înregistra programe folosind DVR. Cu toate acestea, momentan, pe dispozitiv nu există suficient spațiu de stocare ca să funcționeze DVR-ul. Conectați o unitate externă de cel puțin <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB și urmați pașii pentru a o formata ca stocare pe dispozitiv."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Nu există suficient spațiu de stocare"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Programul nu va fi înregistrat, deoarece nu există suficient spațiu de stocare. Ștergeți unele înregistrări existente."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Stocare lipsă"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"O parte din stocarea folosită de DVR lipsește. Pentru a reactiva DVR, conectați unitatea externă folosită anterior. Dacă stocarea externă nu mai este disponibilă, puteți să o eliminați."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Eliminați stocarea?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Tot conținutul înregistrat și toate programările vor fi șterse."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Opriți înregistrarea?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Conținutul înregistrat va fi salvat."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Înregistrarea pentru <xliff:g id="PROGRAMNAME">%1$s</xliff:g> va fi oprită, deoarece există conflicte cu acest program. Conținutul înregistrat va fi salvat."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Înregistrarea a fost programată, dar există conflicte"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Înregistrarea a început, dar există conflicte"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> va fi înregistrat."</string>
@@ -317,17 +310,34 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Același program a fost programat deja pentru înregistrare la <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Înregistrat deja"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Acest program a fost înregistrat deja. Este disponibil în biblioteca DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Înregistrarea serialului a fost programată"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> înregistrări au fost programate pentru <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> de înregistrări au fost programate pentru <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> înregistrare a fost programată pentru <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> înregistrări au fost programate pentru <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> dintre acestea nu vor fi înregistrate din cauza unor conflicte.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> de înregistrări au fost programate pentru <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> dintre acestea nu vor fi înregistrate din cauza unor conflicte.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> înregistrare a fost programată pentru <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Nu va fi înregistrată din cauza unor conflicte.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> înregistrări au fost programate pentru <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episoade din acest serial și din alte seriale nu vor fi înregistrate din cauza unor conflicte.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> de înregistrări au fost programate pentru <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episoade din acest serial și din alte seriale nu vor fi înregistrate din cauza unor conflicte.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> înregistrare a fost programată pentru <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episoade din acest serial și din alte seriale nu vor fi înregistrate din cauza unor conflicte.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> înregistrări au fost programate pentru <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Un episod din alte seriale nu va fi înregistrat din cauza unor conflicte.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> de înregistrări au fost programate pentru <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Un episod din alte seriale nu va fi înregistrat din cauza unor conflicte.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> înregistrare a fost programată pentru <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Un episod din alte seriale nu va fi înregistrat din cauza unor conflicte.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> înregistrări au fost programate pentru <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episoade din alte seriale nu vor fi înregistrate din cauza unor conflicte.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> de înregistrări au fost programate pentru <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episoade din alte seriale nu vor fi înregistrate din cauza unor conflicte.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> înregistrare a fost programată pentru <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episoade din alte seriale nu vor fi înregistrate din cauza unor conflicte.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Programul înregistrat nu a fost găsit."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Înregistrări conexe"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Nicio descriere de program)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="few">%1$d înregistrări</item>
       <item quantity="other">%1$d de înregistrări</item>
@@ -349,6 +359,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Opriți înregistrarea seriei?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Episoadele înregistrate vor rămâne disponibile în biblioteca DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Opriți"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Acum nu este difuzat niciun episod."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nu există episoade disponibile.\nAcestea vor fi înregistrate de îndată ce vor fi disponibile."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="few">(%1$d minute)</item>
@@ -361,4 +372,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, astăzi"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g>, mâine"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Scor"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programe înregistrate"</string>
 </resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 61bef1f..3d2e8ce 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"Моно"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"Стерео"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Управление"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Недавние каналы"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Каналы"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Настройки ТВ"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Настройки PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Команды управления недоступны для этого канала"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Воспроизведение/пауза"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Перемотать вперед"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Субтитры"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Режим"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"Кадр в кадре"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Вкл."</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Выкл."</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Многоканальный"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Ещё каналы"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Настройки"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Источник"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Поменять"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Вкл."</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Выкл."</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Звук"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Главное окно"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Кадр в кадре"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Расположение"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Справа внизу"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Справа вверху"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Слева вверху"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Слева внизу"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Рядом"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Размер"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Крупный"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Мелкий"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Источник"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ТВ (антенна/кабель)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Нет информации о программах"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Неизвестно"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Заблокированный канал"</string>
-    <string name="default_language" msgid="4122326459624337928">"Неизвестный язык"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Неизвестный язык"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Субтитры (%1$d)"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Субтитры"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Выкл."</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Настройка субтитров"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Группировать по"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Эта программа заблокирована"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Для программы не заданы возрастные ограничения"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Возрастное ограничение этой программы: <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Этот вход не поддерживает автоматическое сканирование"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Не удалось начать автосканирование для входа \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -94,7 +76,6 @@
       <item quantity="other">Добавлено %1$d канала</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Нет каналов"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Тюнер"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Родительский контроль"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Вкл."</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Выкл."</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Другие страны"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Нет"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Без рейтинга"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Без классификации"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Блокировать программы без классификации"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Без рейтинга"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Строгие ограничения"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Средние ограничения"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Введите PIN-код, чтобы посмотреть этот канал"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Введите PIN-код, чтобы посмотреть эту программу"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Возрастное ограничение для этой программы: <xliff:g id="RATING">%1$s</xliff:g>. Чтобы посмотреть ее, введите PIN-код."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Для этой программы не указаны возрастные ограничения. Чтобы посмотреть ее, введите PIN-код."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Введите PIN-код"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Чтобы установить родительский контроль, создайте PIN-код"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Введите новый PIN-код"</string>
@@ -139,22 +123,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Неверный PIN-код. Повторите попытку."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN-коды не совпадают. Повторите попытку."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Введите почтовый индекс"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Приложение \"Прямой эфир\" использует почтовый индекс, чтобы создавать телегид специально для вас."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Введите почтовый индекс"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Недопустимый почтовый индекс."</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Настройки"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Настроить список"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Выбрать каналы для телегида"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Источники каналов"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Доступны новые каналы"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Родительский контроль"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Сдвиг времени"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Записывайте прямые трансляции, чтобы потом пересматривать интересные моменты.\nОбратите внимание! Когда включена эта функция, интенсивно используется внутренняя память устройства. В результате срок ее службы может сократиться."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Лицензии открытого ПО"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Лицензии открытого ПО"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Отправить отзыв"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Версия"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Чтобы смотреть этот канал, нажмите стрелку вправо и введите PIN-код."</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Чтобы смотреть эту программу, нажмите стрелку вправо и введите PIN-код."</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Для программы не заданы возрастные ограничения.\nЧтобы посмотреть ее, нажмите на стрелку вправо и введите PIN-код."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Возрастное ограничение этой программы: <xliff:g id="RATING">%1$s</xliff:g>.\nЧтобы посмотреть ее, нажмите на стрелку вправо и введите PIN-код."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Чтобы смотреть этот канал, используйте приложение для просмотра телепрограмм по умолчанию."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Чтобы посмотреть эту программу, используйте приложение для просмотра телепрограмм по умолчанию."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Для программы не заданы возрастные ограничения.\nЧтобы посмотреть ее, используйте приложение для просмотра телепрограмм, установленное по умолчанию."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Возрастное ограничение для этой программы: <xliff:g id="RATING">%1$s</xliff:g>.\nЧтобы посмотреть ее, используйте приложение для просмотра телепрограмм по умолчанию."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Программа заблокирована"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Для программы не заданы возрастные ограничения"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Возрастное ограничение этой программы: <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Только аудио"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Слабый сигнал"</string>
@@ -189,8 +182,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Нажмите кнопку \"ВЫБРАТЬ\""</b>", чтобы открыть меню телевизора."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"ТВ-вход не найден"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Не удается найти ТВ-вход"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP не поддерживается"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Нет источника для режима PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Для ТВ-входа типа \"тюнер\" используйте приложение \"Прямой эфир\""</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Не удалось выполнить настройку"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Действие не поддерживается ни в одном приложении."</string>
@@ -244,6 +235,8 @@
       <item quantity="many">%1$d запланированных записей</item>
       <item quantity="other">%1$d запланированной записи</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Отменить запись"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Остановить запись"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Смотреть"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Смотреть с начала"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Продолжить просмотр"</string>
@@ -278,9 +271,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Если вы выберете слишком много программ для одновременной записи, будут записываться только те, у которых наивысший приоритет."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Сохранить"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Однократная запись имеет самый высокий приоритет"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Отмена"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Отмена"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Удалить"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Остановить"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Смотреть расписание записи"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Только эту серию"</string>
@@ -290,25 +280,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Записать эту программу"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Отменить эту запись"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Смотреть"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Удалить записи…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Можно записать"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Таймер записи установлен"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Конфликт таймера записи"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Идет запись"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Ошибка записи видео"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Выполняется чтение программ. Будет создано расписание записи."</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Выполняется чтение программ…"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Выполняется чтение программ…"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Недавние записи"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Не удалось завершить запись \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\"."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Не удалось завершить записи \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\" и \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\"."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Не удалось завершить записи \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\", \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" и \"<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>\"."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Не удалось завершить запись \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" из-за нехватки места."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Не удалось завершить записи \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\" и \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" из-за нехватки места."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Не удалось завершить записи \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\", \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" и \"<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>\" из-за нехватки места."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Недостаточно места на устройстве"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Вы сможете записывать программы на DVR, однако в настоящее время на вашем устройстве недостаточно места. Подключите внешний накопитель объемом не менее <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> ГБ и отформатируйте его как память устройства."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Вы сможете записывать программы на DVR, однако в настоящее время на вашем устройстве недостаточно места. Подключите внешний накопитель объемом не менее <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> ГБ и отформатируйте его как память устройства."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Недостаточно места"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Недостаточно места для сохранения данных. Попробуйте удалить несколько ненужных записей."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Хранилище отсутствует"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Хранилище не найдено. Подсоедините внешний диск, прежде чем снова включить видеомагнитофон, либо удалите хранилище, если оно недоступно."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Удалить хранилище?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Все созданные и запланированные записи будут стерты."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Остановить запись?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Записанный контент будет сохранен."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Запись сериала \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" будет остановлена из-за конфликта в расписании. Записанный контент сохранится."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Возник конфликт в расписании записи"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Возник конфликт в расписании записи"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Программа \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" будет записана."</string>
@@ -328,17 +321,39 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Запись этой программы уже запланирована на <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Программа уже записана"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Эта программа сохранена в библиотеке видеорекордера."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Запись запланирована"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one">Запланирована <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запись сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\".</item>
+      <item quantity="few">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\".</item>
+      <item quantity="many">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записей сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\".</item>
+      <item quantity="other">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\".</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one">Запланирована <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запись сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>) этого сериала не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="few">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>) этого сериала не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="many">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записей сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>) этого сериала не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="other">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>) этого сериала не будут записаны из-за конфликта в расписании.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one">Запланирована <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> запись сериала \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) этого и других сериалов не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="few">Запланировано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) этого и других сериалов не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="many">Запланировано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записей сериала \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) этого и других сериалов не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="other">Запланировано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) этого и других сериалов не будут записаны из-за конфликта в расписании.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one">Запланирована <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запись сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Одна серия другого сериала не будет записана из-за конфликта в расписании.</item>
+      <item quantity="few">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Одна серия другого сериала не будет записана из-за конфликта в расписании.</item>
+      <item quantity="many">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записей сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Одна серия другого сериала не будет записана из-за конфликта в расписании.</item>
+      <item quantity="other">Запланировано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Одна серия другого сериала не будет записана из-за конфликта в расписании.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one">Запланирована <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> запись сериала \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) других сериалов не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="few">Запланировано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) других сериалов не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="many">Запланировано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записей сериала \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) других сериалов не будут записаны из-за конфликта в расписании.</item>
+      <item quantity="other">Запланировано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записи сериала \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Несколько серий (<xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>) других сериалов не будут записаны из-за конфликта в расписании.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Записанная программа не найдена."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Похожие записи"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(без описания)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d запись</item>
       <item quantity="few">%1$d записи</item>
@@ -362,6 +377,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Остановить запись?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Записанные серии будут сохранены в библиотеке видеорекордера."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Остановить"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"В эфире нет ни одной серии."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Серий пока нет.\nОни будут записаны, как только выйдут в эфир."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d минута)</item>
@@ -375,4 +391,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Сегодня, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Завтра, <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Оценка"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Записанные программы"</string>
 </resources>
diff --git a/res/values-si-v23/strings.xml b/res/values-si-rLK-v23/strings.xml
similarity index 100%
rename from res/values-si-v23/strings.xml
rename to res/values-si-rLK-v23/strings.xml
diff --git a/res/values-si/arrays.xml b/res/values-si-rLK/arrays.xml
similarity index 100%
rename from res/values-si/arrays.xml
rename to res/values-si-rLK/arrays.xml
diff --git a/res/values-si/rating_system_strings.xml b/res/values-si-rLK/rating_system_strings.xml
similarity index 100%
rename from res/values-si/rating_system_strings.xml
rename to res/values-si-rLK/rating_system_strings.xml
diff --git a/res/values-si/strings.xml b/res/values-si-rLK/strings.xml
similarity index 77%
rename from res/values-si/strings.xml
rename to res/values-si-rLK/strings.xml
index eab8c33..2cd7fbf 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"මොනෝ"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ස්ටීරියෝ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"ධාවක පාලන"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"මෑත නාලිකා"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"නාලිකා"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"රූපවාහිනී විකල්ප"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP විකල්ප"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"මෙම නාලිකාව සඳහා Play පාලන ලද නොහැකිය"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"ධාවනය හෝ විරාමය කරන්න"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"වේගයෙන් ඉදිරියට"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"වසන ලද ශිර්ෂ"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"දර්ශන ආකාරය"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"සක්‍රියයි"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"අක්‍රිය කරන්න"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"බහු-ශ්‍රව්‍ය"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"තවත් නාලිකා ගන්න"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"සැකසීම්"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"මුල්‍ය"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"මාරු කරන්න"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"සක්‍රියයි"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"අක්‍රිය කරන්න"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ශබ්දය"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"මූලික"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP කවුළුව"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"පිරිසැලසුම"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"පහළ දකුණ"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ඉහළ දකුණ"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ඉහළ වම"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"පහළ වම"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"පැතෙන් පැත්තට"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"ප්‍රමාණය"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"ලොකු"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"කුඩා"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"මූලය අදානය කරන්න"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (ඇන්ටනාව/කේබලය)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"වැඩසටහන් තොරතුරු නැත"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"තොරතුරු නැත."</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"නාලිකාව අවහිර කරන ලදි"</string>
-    <string name="default_language" msgid="4122326459624337928">"නොදන්නා භාෂාව"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"නොදන්නා භාෂාව"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"වැසූ සිරස්තල %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"වැසූ සිරස්තල"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"අක්‍රිය කරන්න"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ආකෘතිකරණය අභිරුචි කරන්න"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"වර්ග මගින්"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"මෙම වැඩසටහන අවහිර කර තිබේ"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"මෙම වැඩසටහන අගයා නැත"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"මෙම වැඩසටහන <xliff:g id="RATING">%1$s</xliff:g> ලෙස අගයා ඇත"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ආදානය ස්වයංක්‍රිය-සම්මුර්ත කිරීමටසහාය නොදේ"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' සඳහා ස්වයංක්‍රිය-පරිලෝකනය ආරම්භ කිරීමට නොහැකි විය"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">නාලිකා %1$dක් එක් කරන ලදී</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"නාලිකා එකතු කළේ නැත"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"සුසරකය"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"මව්පිය පාලනය"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"සක්‍රිය කරන්න"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"අක්‍රිය කරන්න"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"වෙනත් රටවල්"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"කිසිවක් නැත"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"කිසිවක් නැත"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"අගයා නොමැති"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"අගයා නැති වැඩසටහන් අවහිර කරන්න"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"කිසිවක් නැත"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"ඉහළ සීමා කිරීම්"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"මධ්‍යම සීමා කිරීම්"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"මෙම නාලිකාව නැරඹිමට ඔබගේ PIN එක ඇතුළු කරන්න"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"මෙම වැඩසටහන නැරඹිමට ඔබගේ PIN එක ඇතුළු කරන්න"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"මෙම වැඩසටහන <xliff:g id="RATING">%1$s</xliff:g> ඇගයුම ලබා ඇත. මෙම වැඩසටහන නැරඹිමට ඔබගේ PIN එක ඇතුළු කරන්න"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"මෙම වැඩසටහන අගයා නැත. මෙම වැඩසටහන නැරඹිමට ඔබගේ PIN එක ඇතුළු කරන්න"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"ඔබගේ PIN එක ඇතුළු කරන්න"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"මව්පිය පාලකයක් සකසන්න, PIN එකක් සාදන්න"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"අලුත් PIN එක ඇතුළු කරන්න"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"එම PIN එක වැරදිය. නැවත උත්සාහ කරන්න."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN එක ගැලපී නැත"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"ඔබේ ZIP කේතය ඇතුළු කරන්න."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"සජීව නාලිකා යෙදුම TV නාලිකා සඳහා සම්පූර්ණ වැඩසටහන් මාර්ගෝපදේශයක් සැපයීමට ZIP කේතය භාවිත කරනු ඇත."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"ඔබේ ZIP කේතය ඇතුළු කරන්න"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"වලංගු නොවන ZIP කේතයකි"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"සැකසීම්"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"නාලිකා ලැයිස්තුව අභිමත කරන්න"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"ඔබගේ වැඩසටහන් මාර්ගෝපදේශය සඳහා නාලිකා තෝරන්න"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"නාලිකා මූලාශ්‍ර"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"නව නාලිකා තිබේ"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"මාපිය පාලන"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"ඔබට වැඩසටහන් විරාම කිරීමට හෝ ප්‍රතිවාදනය කිරීමට හැකි වන ලෙස නරඹන අතරතුර පටිගත කරන්න.\nඅවවාදයයි: මෙය අභ්‍යන්තර ගබඩාවෙහි ආයු කාලය ගබඩාව දැඩි ලෙස භාවිත කිරීමෙන් අඩු කළ හැකිය."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"විවෘත මූලාශ්‍ර බලපත්‍ර"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"විවෘත මූලාශ්‍ර වරපත්"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ප්‍රතිපෝෂණය යවන්න"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"අනුවාදය"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"මෙම නාලිකාව නැරඹිමට දකුණ ඔබා PIN එක ඇතුළු කරන්න"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"මෙම වැඩසටහන නැරඹිමට දකුණ ඔබා PIN එක ඇතුළු කරන්න"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"මෙම වැඩසටහන අගයා නැත.\nමෙම වැඩසටහන නැරඹීමට දකුණ ඔබා ඔබගේ PIN එක ඇතුළු කරන්න"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"මෙම වැඩසටහන <xliff:g id="RATING">%1$s</xliff:g> අගයන ලදි.\nමෙම වැඩසටහන නැරඹීමට දකුණ ඔබා ඔබගේ PIN එක ඇතුළු කරන්න."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"මෙම නාලිකාව නැරඹීම සඳහා, පෙරනිමි සජීවි TV යෙදුම භාවිතා කරන්න."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"මෙම වැඩසටහන නැරඹීමට, පෙරනිමි සජීවි TV යෙදුම භාවිතා කරන්න."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"මෙම වැඩසටහන අගයා නැත.\nමෙම වැඩසටහන නැරඹීමට, පෙරනිමි සජීවි TV යෙදුම භාවිත කරන්න."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"මෙම වැඩසටහන <xliff:g id="RATING">%1$s</xliff:g> ලෙස වර්ගීකරණය කර ඇත.\nමෙම වැඩසටහන නැරඹීමට, පෙරනිමි සජීවි TV යෙදුම භාවිතා කරන්න."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"වැඩසටහන අවහිර කරන ලදි"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"මෙම වැඩසටහන අගයා නැත"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"මෙම වැඩසටහන <xliff:g id="RATING">%1$s</xliff:g> ලෙස අගයා ඇත"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ශ්‍රව්‍ය පමණයි"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"දුර්වල සංඥාව"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"TV මෙනුවට පිවිසීමට "<b>"SELECT ඔබන්න"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"TV ආදානය සොයාගැනීමට නොහැකි විය"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV ආදානය සොයාගත නොහැක"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP සහාය දක්වන්නේ නැත"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP සමඟ පෙන්වූ විට අදානයක් එහි නොතිබේ"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"සුසරක වර්ගය ගැලපෙන්නේ නැත; කරුණාකර සුසර කරන වර්ගයේ TV අදානය සඳහා සජීවී නාලිකා යෙදුම දමන්න."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"සුසර කිරීම අසාර්ථක වුණි"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"මෙම ක්‍රියාව හැසිරවීමට යෙදුමක් සොයාගත්තේ නැත"</string>
@@ -226,6 +217,8 @@
       <item quantity="one">පටිගත කිරීම් %1$dක් කාලසටහන්ගත කර ඇත</item>
       <item quantity="other">පටිගත කිරීම් %1$dක් කාලසටහන්ගත කර ඇත</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"පටිගත කිරීම අවලංගු කරන්න"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"පටිගත කිරීම නවත්වන්න"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ඔරලෝසුව"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"මුල සිට ධාවනය කරන්න"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"ධාවනය නැවත පටන් ගැනීම"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"එකම අවස්ථාවේදී පටිගත කිරීමට ප්‍රමාණයට වඩා වැඩි වැඩසටහන් ගණන් ඇති විට, වඩා ඉහළ ප්‍රමුඛතා සහිත ඒවා පමණක් පටිගත කරනු ඇත."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"සුරකින්න"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"එක්-වරක පටිගත කිරීම්වලට වැඩිම ප්‍රමුඛතාව ඇත"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"අවලංගු කර."</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"අවලංගු කරන්න"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"අමතක කරන්න"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"නතර කරන්න"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"පටිගත කිරීමේ කාල සටහන බලන්න"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"මෙම තනි වැඩසටහන"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"ඒ වෙනුවට මෙය පටිගත කරන්න"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"මෙම පටිගත කිරීම අවලංගු කරන්න"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"දැන් නරඹන්න"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"පටිගත කිරීම් මකන්න..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"පටිගත කළ හැකි"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"පටිගත කිරීම කාල සටහන්ගතයි"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"පටිගත කිරීමේ ගැටුම"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"පටිගත කරමින්"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"පටිගත කිරීම අසාර්ථක විය"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"පටිගත කිරීමේ කාලසටහන් සෑදීමට වැඩසටහන් කියවමින්"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"කියවීමේ වැඩසටහන්"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"කියවීමේ වැඩසටහන්"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"මෑත පටිගත කිරීම් බලන්න"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> හි පටිගත කිරීම අසම්පූර්ණයි."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> සහ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> හි පටිගත කිරීම් අසම්පූර්ණයි."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> සහ <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> හි පටිගත කිරීම් අසම්පූර්ණයි."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"ප්‍රමාණවත් නොවන ගබඩාව නිසා <xliff:g id="PROGRAMNAME">%1$s</xliff:g> හි පටිගත කිරීම සම්පූර්ණ නොකරන ලදී."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"ප්‍රමාණවත් නොවන ගබඩාව නිසා <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> සහ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> හි පටිගත කිරීම් සම්පූර්ණ නොකරන ලදී."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"ප්‍රමාණවත් නොවන ගබඩාව නිසා <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> සහ <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> හි පටිගත කිරීම් සම්පූර්ණ නොකරන ලදී."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR සඳහා වැඩිපුර ගබඩාව අවශ්‍යයි"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ඔබට DVR සමගින් වැඩසටහන් පටිගත කිරීමට හැකි වනු ඇත. කෙසේ වෙතත් දැන් DVR ක්‍රියා කිරීම සඳහා ඔබේ උපාංගයේ ප්‍රමාණවත් තරම් ගබඩාව නැත. කරුණාකර <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB හෝ ඊට වඩා විශාල බාහිර ධාවකයක් සම්බන්ධ කර එය උපාංග ගබඩාව ලෙස ෆෝමැට් කිරීමට පහත පියවර අනුගමනය කරන්න."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"ඔබට DVR සමගින් වැඩසටහන් පටිගත කිරීමට හැකි වනු ඇත. කෙසේ වෙතත් දැන් DVR ක්‍රියා කිරීම සඳහා ඔබේ උපාංගයේ ප්‍රමාණවත් තරම් ගබඩාව නැත. කරුණාකර <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB හෝ ඊට වඩා විශාල බාහිර ධාවකයක් සම්බන්ධ කර එය උපාංග ගබඩාව ලෙස ෆෝමැට් කිරීමට පහත පියවර අනුගමනය කරන්න."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"ප්‍රමාණවත් තරම් ගබඩා ඉඩ නැත"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"ප්‍රමාණවත් තරම් ගබඩා ඉඩ නොමැති නිසා මෙම වැඩසටහන පටිගත කළ නොහැකි වනු ඇත. පවතින පටිගත කිරීම් සමහරක් මැකීම උත්සාහ කරන්න."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"අස්ථානගත ගබඩාව"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR මගින් භාවිත කළ ගබඩා සමහරක් අස්ථානගතය. කරුණාකර DVR නැවත-සබල කිරීමට ඔබ පෙරදී භාවිත කළ බාහිර drive සම්බන්ධ කරන්න. විකල්පව, එය තවදුරටත් ලබා ගත නොහැකි නම් ඔබට ගබඩාව අමතක කිරීමට තේරිය හැකිය."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"ගබඩාව අමතකද?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"ඔබේ පටිගත කළ සියලු අන්තර්ගත සහ කාල සටහන් අහිමි වනු ඇත."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"පටිගත කිරීම නවත්වන්නද?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"පටිගත කළ අන්තර්ගතය සුරැකෙනු ඇත."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"මෙම වැඩසටහන සමගින් වන ගැටුම් නිසා <xliff:g id="PROGRAMNAME">%1$s</xliff:g> හි පටිගත කිරීම නවත්වන ලදී. පටිගත කරන ලද අන්තර්ගතය සුරකිනු ඇත."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"පටිගත කිරීම කාල සටහන්ගත කර ඇති නමුත් ගැටුම් ඇත"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"පටිගත කිරීම ආරම්භ කර ඇති නමුත් ගැටුම් ඇත"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> පටිගත කරනු ඇත."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"එම වැඩසටහනම <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>ට පටිගත කිරීමට කාල සටහන්ගත කර ඇත."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"දැනටමත් පටිගත කර ඇත"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"මෙම වැඩසටහන දැනටමත් පටිගත කර ඇත. එය DVR පුස්තකාලය තුළදී ලබා ගත හැකිය."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"මාලා පටිගත කිරීම කාලසටහන්ගත කරන ලදී"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_3">%2$s</xliff:g> සඳහා කාල සටහන්ගත කර ඇත.</item>
+      <item quantity="other">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_3">%2$s</xliff:g> සඳහා කාල සටහන්ගත කර ඇත.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_3">%2$s</xliff:g> සඳහා කාල සටහන්ගත කර ඇත. ඒවායින් <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>ක් ගැටුම් නිසා පටිගත නොකරනු ඇත.</item>
+      <item quantity="other">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_3">%2$s</xliff:g> සඳහා කාල සටහන්ගත කර ඇත. ඒවායින් <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>ක් ගැටුම් නිසා පටිගත නොකරනු ඇත.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_4">%2$s</xliff:g> සඳහා කාල සටහන්ගත කර ඇත. මෙම මාලාවෙහි සහ වෙනත් මාලාවල කථාංග <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>ක් ගැටුම් නිසා පටිගත නොකරනු ඇත.</item>
+      <item quantity="other">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_4">%2$s</xliff:g> සඳහා කාල සටහන්ගත කර ඇත. මෙම මාලාවෙහි සහ වෙනත් මාලාවල කථාංග <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>ක් ගැටුම් නිසා පටිගත නොකරනු ඇත.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_3">%2$s</xliff:g> සඳහා කාලසටහන්ගත කර ඇත. වෙනත් මාලාවල කථාංග 1ක් ගැටුම් නිසා පටිගත නොකරනු ඇත.</item>
+      <item quantity="other">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_3">%2$s</xliff:g> සඳහා කාලසටහන්ගත කර ඇත. වෙනත් මාලාවල කථාංග 1ක් ගැටුම් නිසා පටිගත නොකරනු ඇත.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_4">%2$s</xliff:g> සඳහා කාල සටහන්ගත කර ඇත. වෙනත් මාලාවේ කථාංග <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>ක් ගැටුම් නිසා පටිගත නොකරනු ඇත.</item>
+      <item quantity="other">පටිගත කිරීම් <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g>ක් <xliff:g id="SERIESNAME_4">%2$s</xliff:g> සඳහා කාල සටහන්ගත කර ඇත. වෙනත් මාලාවේ කථාංග <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>ක් ගැටුම් නිසා පටිගත නොකරනු ඇත.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"පටිගත කළ වැඩසටහන හමු නොවීය."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"අදාළ පටිගත කිරීම්"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(වැඩසටහන් විස්තරය නැත)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">පටිගත කිරීම් %1$d</item>
       <item quantity="other">පටිගත කිරීම් %1$d</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"මාලා පටිගත කිරීම නවත්වන්නද?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"පටිගත කළ කථාංග DVR පුස්තකාලය තුළ ලබා ගත හැකිව පවතිනු ඇත."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"නවත්වන්න"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"දැන් ගුවනේ කථාංග නැත."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"ලබා ගත හැකි කථාංග නැත.\nඒවා ලබා ගත හැකි වූ විට පටිගත කරනු ඇත."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(මිනිත්තු %1$d)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"අද <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"හෙට <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"ලකුණු"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"පටිගත කළ වැඩසටහන්"</string>
 </resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 78d94c7..1d747d7 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -20,54 +20,35 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Ovládanie prehrávania"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Nedávne kanály"</string>
-    <string name="menu_title_options" msgid="7184594626814914022">"Možnosti TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Možnosti PIP"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanály"</string>
+    <string name="menu_title_options" msgid="7184594626814914022">"Možnosti televízie"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Pre tento kanál nie sú k dispozícii ovládacie prvky prehrávania"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Prehrať alebo pozastaviť"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Pretočiť dopredu"</string>
     <string name="play_controls_description_fast_rewind" msgid="953488122681015803">"Pretočiť späť"</string>
     <string name="play_controls_description_skip_next" msgid="1603587562124694592">"Ďalej"</string>
     <string name="play_controls_description_skip_previous" msgid="3858447678278021381">"Naspäť"</string>
-    <string name="channels_item_program_guide" msgid="2889807207930678418">"Program. sprievodca"</string>
-    <string name="channels_item_setup" msgid="6557412175737379022">"Dostupné sú nové kanály"</string>
+    <string name="channels_item_program_guide" msgid="2889807207930678418">"Televízny program"</string>
+    <string name="channels_item_setup" msgid="6557412175737379022">"Dostupné nové kanály"</string>
     <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"Spustiť aplikáciu <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Skryté titulky"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Režim zobrazenia"</string>
-    <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Zapnuté"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Vypnuté"</string>
-    <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
+    <string name="options_item_pip" msgid="3951350386626879645">"Obraz v obraze"</string>
+    <string name="options_item_multi_audio" msgid="5118851311937896923">"Viackanálový zvuk"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Ďalšie kanály"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Nastavenia"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Zdroj"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Zameniť"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Zapnuté"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Vypnuté"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Zvuk"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Hlavné"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Okno PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Rozloženie"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Vpravo dole"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Vpravo hore"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Vľavo hore"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Vľavo dole"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Vedľa seba"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Rozmery"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Veľké"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Malé"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Zdroj vstupu"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (anténa/kábel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Žiadne informácie o programe"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Žiadne informácie"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Zablokovaný kanál"</string>
-    <string name="default_language" msgid="4122326459624337928">"Neznámy jazyk"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Neznámy jazyk"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Skryté titulky: %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Skryté titulky"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Vypnuté"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Prispôsobiť formát"</string>
     <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Nastavenie systémových predvolieb pre skryté titulky"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Režim zobrazenia"</string>
-    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Multi-audio"</string>
+    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Viackanálový zvuk"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"mono"</string>
     <string name="multi_audio_channel_stereo" msgid="3758995659214256587">"stereo"</string>
     <string name="multi_audio_channel_surround_6" msgid="6066304966228963942">"Priestorový zvuk 5.1"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Zoskupiť podľa"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Tento program je zablokovaný."</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Tento program nemá hodnotenie"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Hodnotenie tohto programu je <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Vstup nepodporuje automatické vyhľadávanie"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Nepodarilo sa automaticky prehľadať vstup <xliff:g id="TV_INPUT">%s</xliff:g>"</string>
@@ -94,7 +76,6 @@
       <item quantity="one">%1$d pridaný kanál</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Žiadne pridané kanály"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Rodič. kontrola"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Zapnuté"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Vypnuté"</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Iné krajiny"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Žiadny"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Žiadny"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Nehodnotené"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokovať nehodnotené programy"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Žiadne"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Silné obmedzenia"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Stredné obmedzenia"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Zadanie kódu PIN na pozeranie tohto kanála"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Zadanie kódu PIN na pozeranie tohto programu"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Tento program má hodnotenie <xliff:g id="RATING">%1$s</xliff:g>. Ak ho chcete pozerať, zadajte kód PIN."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Tento program nemá hodnotenie. Ak ho chcete pozerať, zadajte kód PIN."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Zadanie kódu PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Ak chcete nastaviť rodičovskú kontrolu, vytvorte kód PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Zadajte nový kód PIN"</string>
@@ -139,22 +123,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Kód PIN bol zadaný chybne. Skúste to znova."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Kód PIN nesúhlasí. Skúste to znova."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Zadajte svoje PSČ."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Aplikácia Televízia online vám na základe poštového smerovacieho čísla poskytne kompletný program televíznych kanálov."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Zadajte svoje PSČ"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Neplatné PSČ"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Nastavenia"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Prispôsobiť zoznam kanálov"</string>
-    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Vybrať kanály pre televízny program"</string>
+    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Vyberte kanály pre televízny program"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Zdroje kanálov"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"K dispozícii sú nové kanály"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Rodičovská kontrola"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Posunutie času"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Zaznamenávajte pozerané programy vysielané naživo, aby ste ich mohli pozastaviť alebo pretočiť späť.\nUpozornenie: Intenzívnym využívaním interného úložiska môže dôjsť ku skráteniu jeho životnosti."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licencie open source"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Licencie open source"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Odoslať spätnú väzbu"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Verzia"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Ak chcete sledovať tento kanál, stlačte šípku vpravo a zadajte kód PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Ak chcete sledovať tento program, stlačte šípku doprava a zadajte kód PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Tento program nemá hodnotenie.\nAk ho chcete pozerať, stlačte šípku doprava a zadajte PIN."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Hodnotenie tohto programu je <xliff:g id="RATING">%1$s</xliff:g>.\nAk chcete sledovať tento program, stlačte šípku doprava a zadajte kód PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Ak chcete sledovať tento kanál, použite predvolenú aplikáciu Live TV."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Ak chcete sledovať tento program, použite predvolenú aplikáciu Live TV."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Tento program nemá hodnotenie.\nAk ho chcete pozerať, použite predvolenú aplikáciu Live TV."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Tento program má hodnotenie <xliff:g id="RATING">%1$s</xliff:g>.\nAk ho chcete sledovať, použite predvolenú aplikáciu Live TV."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Program je zablokovaný"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Tento program nemá hodnotenie"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Hodnotenie tohto programu je <xliff:g id="RATING">%1$s</xliff:g>."</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Iba zvuk"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Slabý signál"</string>
@@ -179,7 +172,7 @@
     <string name="setup_input_new" msgid="3337725672277046798">"Nové"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Nenastavené"</string>
     <string name="setup_store_action_title" msgid="4083402039720973414">"Získať ďalšie zdroje"</string>
-    <string name="setup_store_action_description" msgid="6820482635042445297">"Prehliadajte aplikácie, ktoré ponúkajú televíziu online"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Aplikácie, ponúkajúce televíziu online"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"K dispozícii sú nové zdroje kanálov"</string>
     <string name="new_sources_description" msgid="749649005588426813">"K dispozícii sú nové zdroje s ďalšími kanálmi.\nMôžete ich nastaviť hneď alebo neskôr v nastavení zdrojov kanálov."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Nastaviť"</string>
@@ -189,8 +182,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Stlačením tlačidla VYBRAŤ"</b>" prejdete do TV ponuky."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Nenašiel sa žiadny TV vstup"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV vstup sa nenašiel"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Funkcia Obraz v obraze (PIP) nie je podporovaná"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Neexistuje vstup, ktorý by mohla funkcia PIP zobraziť"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Typ tunera nie je vhodný. Pre TV vstup typu tunera spustite aplikáciu Aktívne kanály."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Ladenie zlyhalo"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Aplikácia potrebná na spracovanie tejto akcie sa nenašla."</string>
@@ -199,7 +190,7 @@
     <string name="msg_back_key_guide" msgid="7404682718828721924">"Kláves Späť je určený pre pripojené zariadenie. Aplikáciu ukončite stlačením tlačidla Domov."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Aktívne kanály potrebujú povolenie na čítanie televíznych programov."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Nastavte si zdroje"</string>
-    <string name="setup_sources_description" msgid="5695518946225445202">"Televízia online spája zážitok z tradičných televíznych kanálov so streamovaním kanálov z aplikácií. \n\nZačnite nastavením zdrojov kanálov, ktoré už máte nainštalované. Prípadne si prehliadnite Obchod Google Play a získajte ďalšie aplikácie, ktoré poskytujú televíziu online."</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"Televízia online spája tradičné televízne kanály so streamovanými kanálmi z aplikácií. \n\nAk chcete začať, nastavte si zdroje kanálov, ktoré už máte nainštalované. Prípadne si môžete v Obchode Google Play vyhľadať ďalšie aplikácie, ktoré ponúkajú televíziu online."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Nahrávanie a plány"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minút"</string>
     <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 minút"</string>
@@ -244,6 +235,8 @@
       <item quantity="other">%1$d plánovaných záznamov</item>
       <item quantity="one">%1$d plánovaný záznam</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Zrušiť zaznamenávanie"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Zastaviť zaznamenávanie"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Prehrať"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Prehrať od začiatku"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Obnoviť prehrávanie"</string>
@@ -278,9 +271,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Keď naplánujete nahrávanie príliš veľa programov súčasne, zaznamenajú sa iba programy s najvyššími prioritami."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Uložiť"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Jednorazové záznamenávania majú najvyššiu prioritu"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Zrušiť"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Zrušiť"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Odstrániť"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Zastaviť"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Zobraziť rozvrh nahrávania"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Iba tento program"</string>
@@ -290,25 +280,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Zaznamenať radšej tento program"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Zrušiť tento záznam"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Pozrieť"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Odstrániť nahratý obsah..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Je možné nahrať"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Nahrávanie je naplánované"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Konflikt nahrávania"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Nahráva sa"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Nahrávanie zlyhalo"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Čítajú sa programy s cieľom vytvoriť plány zaznamenávania"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Načítavajú sa programy"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Načítavajú sa programy"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Zobraziť nedávne nahrávky"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Záznam programu <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nie je úplný."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Záznamy programov <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> a <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nie sú úplné."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Záznamy programov <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> a <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nie sú úplné."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Zaznamenávanie programu <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nebolo dokončené z dôvodu nedostatku miesta v úložisku."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Zaznamenávanie programov <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> a <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nebolo dokončené z dôvodu nedostatku miesta v úložisku."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Zaznamenávanie programov <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> a <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nebolo dokončené z dôvodu nedostatku miesta v úložisku."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR vyžaduje viac miesta v úložisku"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Budete môcť zaznamenávať programy pomocou zariadenia DVR. Teraz však v úložisku vášho zariadenia nie je dostatok miesta na fungovanie zariadenia DVR. Pripojte externý disk s minimálnou kapacitou <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB a podľa uvedených krokov ho naformátujte ako úložisko zariadenia."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Budete môcť zaznamenávať programy pomocou zariadenia DVR. Teraz však v úložisku vášho zariadenia nie je dostatok miesta na fungovanie zariadenia DVR. Pripojte externý disk s minimálnou kapacitou <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB a podľa uvedených krokov ho naformátujte ako úložisko zariadenia."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Nedostatok úložiska"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Tento program nebude nahratý z dôvodu nedostatku úložiska. Skúste odstrániť časť nahratého obsahu."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Chýba úložisko"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Určitá časť úložiska využitého zariadením DVR chýba. Pred opätovným povolením zariadenia DVR pripojte externý disk, ktorý ste predtým používali. Prípadne môžete úložisko odstrániť, ak už nie je ďalej k dispozícii."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Odstrániť úložisko?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Všetok váš zaznamenaný obsah a plány budú stratené."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Zastaviť nahrávanie?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Nahraný obsah sa uloží."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Zaznamenávanie relácie <xliff:g id="PROGRAMNAME">%1$s</xliff:g> bude zastavené, pretože koliduje s týmto programom. Zaznamenaný obsah sa uloží."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Nahrávanie je naplánované, ale obsahuje konflikty"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Záznam sa spustil, ale obsahuje konflikty"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Zaznamená sa program <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -328,17 +321,39 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Zaznamenanie rovnakého programu už bolo naplánované na <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Už je zaznamenané"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Tento program je už zaznamenaný. Nájdete ho v knižnici zariadenia DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Zaznamenávanie relácie bolo naplánované"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="few">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> boli naplánované <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamy.</item>
+      <item quantity="many">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> bolo naplánovaného <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamu.</item>
+      <item quantity="other">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> bolo naplánovaných <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamov.</item>
+      <item quantity="one">Pre seriál <xliff:g id="SERIESNAME_1">%2$s</xliff:g> bol naplánovaný <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> záznam.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="few">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> boli naplánované <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamy. Z dôvodu konfliktov sa nezaznamenajú niektoré epizódy (počet: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>).</item>
+      <item quantity="many">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> bolo naplánovaného <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamu. Z dôvodu konfliktov sa nezaznamenajú niektoré epizódy (počet: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>)</item>
+      <item quantity="other">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> bolo naplánovaných <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamov. Z dôvodu konfliktov sa nezaznamenajú niektoré epizódy (počet: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>)</item>
+      <item quantity="one">Pre seriál <xliff:g id="SERIESNAME_1">%2$s</xliff:g> bol naplánovaný <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> záznam. Z dôvodu konfliktov sa nezaznamená.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="few">Pre seriál <xliff:g id="SERIESNAME_4">%2$s</xliff:g> boli naplánované <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> záznamy. Z dôvodu konfliktov sa nezaznamenajú niektoré epizódy z tohto seriálu a ďalších seriálov (počet: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="many">Pre seriál <xliff:g id="SERIESNAME_4">%2$s</xliff:g> bolo naplánovaného <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> záznamu. Z dôvodu konfliktov sa nezaznamenajú niektoré epizódy z tohto seriálu a ďalších seriálov (počet: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="other">Pre seriál <xliff:g id="SERIESNAME_4">%2$s</xliff:g> bolo naplánovaných <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> záznamov. Z dôvodu konfliktov sa nezaznamenajú niektoré epizódy z tohto seriálu a ďalších seriálov (počet: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="one">Pre seriál <xliff:g id="SERIESNAME_1">%2$s</xliff:g> bol naplánovaný <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> záznam. Z dôvodu konfliktov sa nezaznamenajú niektoré epizódy z tohto seriálu a ďalších seriálov (počet: <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g>).</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="few">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> boli naplánované <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamy.Z dôvodu konfliktov nebude zaznamenaná 1 epizóda inej relácie.</item>
+      <item quantity="many">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> bolo naplánovaného <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamu.Z dôvodu konfliktov nebude zaznamenaná 1 epizóda inej relácie.</item>
+      <item quantity="other">Pre seriál <xliff:g id="SERIESNAME_3">%2$s</xliff:g> bolo naplánovaných <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> záznamov.Z dôvodu konfliktov nebude zaznamenaná 1 epizóda inej relácie.</item>
+      <item quantity="one">Pre seriál <xliff:g id="SERIESNAME_1">%2$s</xliff:g> bol naplánovaný <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> záznam.Z dôvodu konfliktov nebude zaznamenaná 1 epizóda inej relácie.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="few">Pre seriál <xliff:g id="SERIESNAME_4">%2$s</xliff:g> boli naplánované <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> záznamy. Z dôvodu konfliktov sa nezaznamenajú epizódy z iného seriálu (počet: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="many">Pre seriál <xliff:g id="SERIESNAME_4">%2$s</xliff:g> bolo naplánovaného <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> záznamu. Z dôvodu konfliktov sa nezaznamenajú epizódy z iného seriálu (počet: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="other">Pre seriál <xliff:g id="SERIESNAME_4">%2$s</xliff:g> bolo naplánovaných <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> záznamov. Z dôvodu konfliktov sa nezaznamenajú epizódy z iného seriálu (počet: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>).</item>
+      <item quantity="one">Pre seriál <xliff:g id="SERIESNAME_1">%2$s</xliff:g> bol naplánovaný <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> záznam. Z dôvodu konfliktov sa nezaznamenajú epizódy z iného seriálu (počet: <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g>).</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Zaznamenaný program sa nenašiel."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Súvisiace nahrávky"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Žiadny popis programu)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="few">%1$d záznamy</item>
       <item quantity="many">%1$d záznamu</item>
@@ -349,7 +364,7 @@
     <string name="dvr_schedules_deletion_info" msgid="2837586459900271031">"Program <xliff:g id="PROGRAMNAME">%1$s</xliff:g> bol odstránený z rozvrhu nahrávania"</string>
     <string name="dvr_schedules_tuner_conflict_will_be_partially_recorded" msgid="5280490298546908729">"Z dôvodu konfliktu tunerov bude nahratá iba časť obsahu."</string>
     <string name="dvr_schedules_tuner_conflict_will_not_be_recorded_info" msgid="5065400564003201095">"Z dôvodu konfliktu tunerov obsah nebude nahratý."</string>
-    <string name="dvr_schedules_empty_state" msgid="1291529283469462741">"Nemáte naplánované žiadne záznamy.\nZaznamenávanie môžete naplánovať z televízneho programu."</string>
+    <string name="dvr_schedules_empty_state" msgid="1291529283469462741">"Nemáte naplánované žiadne záznamy.\nZáznam môžete naplánovať z televízneho programu."</string>
     <plurals name="dvr_series_schedules_header_description" formatted="false" msgid="9077188267856194114">
       <item quantity="few">%1$d konflikty nahrávania</item>
       <item quantity="many">%1$d konfliktu nahrávania</item>
@@ -362,6 +377,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Zastaviť nahrávanie série?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Nahrané epizódy zostanú k dispozícii v knižnici DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Zastaviť"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Momentálne nie sú vysielané žiadne epizódy."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nie sú k dispozícii žiadne epizódy.\nZaznamenajú sa, keď budú dostupné."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="few">(%1$d minúty)</item>
@@ -375,4 +391,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Dnes: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Zajtra: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Skóre"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Zaznamenané programy"</string>
 </resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 6e79cac..7fac034 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Kontrolniki predvajanja"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Nedavni kanali"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanali"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Možnosti za TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Možnosti za PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Kontrolniki za predvajanje niso na voljo za ta kanal"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Predvajanje ali zaustavitev"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Previjanje naprej"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Podnapisi"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Način prikaza"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Vklopljeno"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Izklopljeno"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multizvok"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Več kanalov"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Nastavitve"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Vir"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Zamenjaj"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Vklopljeno"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Izklopljeno"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Zvok"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Glavno"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Okno PIP-a"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Postavitev"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Spodaj desno"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Zgoraj desno"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Zgoraj levo"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Spodaj levo"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Vzporedno"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Velikost"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Veliko"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Majhno"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Vir vhoda"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antena/kabelska)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Ni informacij o programu"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Ni informacij"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blokiran kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Neznan jezik"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Neznan jezik"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Podnapisi %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Podnapisi"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Izklopljeno"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Oblikovanje po meri"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Razvrsti po:"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Ta program je blokiran"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ta oddaja nima kategorije vsebine"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Ta program ima kategorijo vsebine <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Vhod ne podpira samodejnega iskanja"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Samodejnega iskanja za »<xliff:g id="TV_INPUT">%s</xliff:g>« ni mogoče začeti"</string>
@@ -94,7 +76,6 @@
       <item quantity="other">%1$d dodanih kanalov</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Ni dodanih kanalov"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Sprejemnik"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Starševski nadzor"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Vklopljeno"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Izklopljeno"</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Druge države"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Brez"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Brez"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Brez kategorije vsebine"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blokiranje oddaj brez kat. vs."</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Brez"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Visoke omejitve"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Srednje omejitve"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Vnesite kodo PIN, če želite gledati ta kanal"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Vnesite kodo PIN, če želite gledati to oddajo"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Ta oddaja ima kategorijo vsebine <xliff:g id="RATING">%1$s</xliff:g>. Vnesite kodo PIN, če si želite ogledati to oddajo."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ta oddaja nima kategorije vsebine. Vnesite kodo PIN, če jo želite gledati."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Vnos kode PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Če želite nastaviti starševski nadzor, ustvarite kodo PIN."</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Vnesite novo kodo PIN"</string>
@@ -139,22 +123,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Koda PIN je bila napačna. Poskusite znova."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Poskusite znova. Koda PIN se ne ujema."</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Vnos poštne številke."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Aplikacija Televizija v živo uporablja poštno številko za posredovanje popolnega programskega vodnika za televizijske kanale."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Vnesite poštno številko"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Neveljavna poštna številka"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Nastavitve"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Prilagajanje seznama kanalov"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Izbira kanalov za programski vodnik"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Viri kanalov"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Na voljo so novi kanali"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Starševski nadzor"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Časovni zamik"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Snemanje med gledanjem, da lahko oddaje v živo zaustavite ali previjete nazaj.\nOpozorilo: zaradi intenzivne rabe shrambe se lahko s tem skrajša življenjska doba notranje shrambe."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Odprtokodne licence"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Odprtokodne licence"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Pošljite povratne informacije"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Različica"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Če želite gledati ta kanal, pritisnite v desno in vnesite kodo PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Če želite gledati ta program, pritisnite v desno in vnesite kodo PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ta oddaja nima kategorije vsebine.\nČe jo želite gledati, pritisnite desno smerno tipko in vnesite kodo PIN."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Ta program ima kategorijo vsebine <xliff:g id="RATING">%1$s</xliff:g>.\nČe ga želite gledati, pritisnite v desno in vnesite kodo PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Če želite gledati ta kanal, uporabite privzeto aplikacijo za TV v živo."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Če želite gledati to oddajo, uporabite privzeto aplikacijo za TV v živo."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ta oddaja nima kategorije vsebine.\nČe jo želite gledati, uporabite aplikacijo za TV v živo."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Ta oddaja ima kategorijo vsebine <xliff:g id="RATING">%1$s</xliff:g>.\nČe jo želite gledati, uporabite privzeto aplikacijo za TV v živo."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Oddaja je blokirana"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ta oddaja nima kategorije vsebine"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Ta program ima kategorijo vsebine <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Samo zvok"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Šibek signal"</string>
@@ -189,8 +182,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Pritisnite »IZBIRA«"</b>", če želite dostopati do menija TV-ja."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Ni TV-vhodov"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Ni mogoče najti TV-vhoda"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Slika v sliki ni podprta"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Ni vhoda, ki bi omogočal prikaz s sliko v sliki (PIP)"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Vrsta sprejemnika ni ustrezna. Zaženite aplikacijo Kanali v živo za uporabo TV-vhoda, ki deluje kot sprejemnik."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Nastavljanje kanalov ni uspelo"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Za to dejanje ni bilo mogoče najti nobene aplikacije."</string>
@@ -201,10 +192,10 @@
     <string name="setup_sources_text" msgid="4988039637873759839">"Nastavitev virov"</string>
     <string name="setup_sources_description" msgid="5695518946225445202">"Kanali v živo združujejo izkušnjo običajnih TV-kanalov in pretočno predvajanje kanalov, ki ga omogočajo aplikacije. \n\nZačnite tako, da nastavite vire kanalov, ki so že nameščeni. V Trgovini Google Play lahko tudi poiščete druge aplikacije, ki omogočajo kanale v živo."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Posnetki in razporedi"</string>
-    <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 min"</string>
-    <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 min"</string>
+    <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minut"</string>
+    <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 minut"</string>
     <string name="recording_start_dialog_1_hour_duration" msgid="7159533207022355641">"1 h"</string>
-    <string name="recording_start_dialog_3_hours_duration" msgid="295984419320006238">"3 h"</string>
+    <string name="recording_start_dialog_3_hours_duration" msgid="295984419320006238">"3 ure"</string>
     <string name="dvr_main_recent" msgid="2553805424822806495">"Nedavno"</string>
     <string name="dvr_main_scheduled" msgid="7837260963086408492">"Načrtovano"</string>
     <string name="dvr_main_series" msgid="8278256687595691676">"Nanizanka"</string>
@@ -244,6 +235,8 @@
       <item quantity="few">%1$d načrtovani posnetki</item>
       <item quantity="other">%1$d načrtovan. posnetkov</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Prekliči snemanje"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Ustavi snemanje"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Gledanje"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Predvajaj od začetka"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Nadaljuj predvajanje"</string>
@@ -278,9 +271,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Če je nastavljeno snemanje preveč oddaj ob istem času, bodo posnete samo oddaje z višjo prednostjo."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Shrani"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Enkratna snemanja imajo najvišjo prednost"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Prekliči"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Prekliči"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Pozabi"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Ustavi"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Ogled razporeda snemanja"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Samo to oddajo"</string>
@@ -290,25 +280,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Snemanje tega namesto drugega"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Preklic tega snemanja"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Ogled"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Izbris posnetkov …"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Omogoča snemanje"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Čas snemanja nastavljen"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Posnetek v sporu"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Snemanje"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Snemanje ni uspelo"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Branje oddaj za ustvarjanje razporedov snemanja"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Branje oddaj"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Branje oddaj"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Ogled nedavnih posnetkov"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Posnetek vsebine <xliff:g id="PROGRAMNAME">%1$s</xliff:g> je nepopoln."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Posnetka vsebin <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> in <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> sta nepopolna."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Posnetki vsebin <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> in <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> so nepopolni."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Snemanje vsebine <xliff:g id="PROGRAMNAME">%1$s</xliff:g> se ni dokončalo zaradi pomanjkanja prostora za shranjevanje."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Snemanje vsebin <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> in <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> se ni dokončalo zaradi pomanjkanja prostora za shranjevanje."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Snemanje vsebin <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> in <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> se ni dokončalo zaradi pomanjkanja prostora za shranjevanje."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Digitalni videorekorder potrebuje več shrambe"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Z digitalnim videorekorderjem boste lahko snemali oddaje, vendar v napravi ni dovolj shrambe, potrebne za njegovo delovanje. Priključite zunanji pogon velikosti <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB ali več in upoštevajte navodila, da ga formatirate kot shrambo naprave."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Z digitalnim videorekorderjem boste lahko snemali oddaje, vendar v napravi ni dovolj shrambe, potrebne za njegovo delovanje. Priključite zunanji pogon velikosti <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB ali več in upoštevajte navodila, da ga formatirate kot shrambo naprave."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Ni dovolj prostora za shranjevanje"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Ta program ne bo posnet, ker ni dovolj prostora za shranjevanje. Poskusite izbrisati nekatere obstoječe posnetke."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Manjkajoča shramba"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Del shrambe, ki jo uporablja digitalni videorekorder, manjka. Povežite zunanji pogon, ki ste ga že uporabljali, če želite znova omogočiti digitalni videorekorder. Če shramba ni več na voljo, jo lahko tudi pozabite."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Želite pozabiti shrambo?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Posneta vsebina in razporedi bodo izgubljeni."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Želite ustaviti snemanje?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Posneta vsebina bo shranjena."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Snemanje vsebine <xliff:g id="PROGRAMNAME">%1$s</xliff:g> bo ustavljeno, ker je v sporu s tem programom. Posneta vsebina bo shranjena."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Snemanje je nastavljeno, ampak obstajajo spori"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Snemanje se je začelo, vendar so spori"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Oddaja <xliff:g id="PROGRAMNAME">%1$s</xliff:g> bo posneta."</string>
@@ -328,17 +321,39 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Snemanje iste oddaje je že nastavljeno za ob <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Že posneto"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Ta oddaja je že posneta. Na voljo je v knjižnici digitalnega videorekorderja."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Snemanje serije je načrtovano"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetek je načrtovan za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetka sta načrtovana za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetki so načrtovani za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetkov je načrtovanih za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetek je načrtovan za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Zaradi sporov jih ne bo posnetih toliko: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetka sta načrtovana za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Zaradi sporov jih ne bo posnetih toliko: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetki so načrtovani za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Zaradi sporov jih ne bo posnetih toliko: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetkov je načrtovanih za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Zaradi sporov jih ne bo posnetih toliko: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> posnetek je načrtovan za serijo <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Zaradi sporov ne bo posnetih toliko epizod te serije in drugih serij: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> posnetka sta načrtovana za serijo <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Zaradi sporov ne bo posnetih toliko epizod te serije in drugih serij: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> posnetki so načrtovani za serijo <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Zaradi sporov ne bo posnetih toliko epizod te serije in drugih serij: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> posnetkov je načrtovanih za serijo <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Zaradi sporov ne bo posnetih toliko epizod te serije in drugih serij: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetek je načrtovan za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Zaradi sporov ne bo posneta 1 epizoda druge serije.</item>
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetka sta načrtovana za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Zaradi sporov ne bo posneta 1 epizoda druge serije.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetki so načrtovani za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Zaradi sporov ne bo posneta 1 epizoda druge serije.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> posnetkov je načrtovanih za serijo <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Zaradi sporov ne bo posneta 1 epizoda druge serije.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> posnetek je načrtovan za serijo <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Zaradi sporov ne bo posnetih toliko epizod drugih serij: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="two"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> posnetka sta načrtovana za serijo <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Zaradi sporov ne bo posnetih toliko epizod drugih serij: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> posnetki so načrtovani za serijo <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Zaradi sporov ne bo posnetih toliko epizod drugih serij: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> posnetkov je načrtovanih za serijo <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Zaradi sporov ne bo posnetih toliko epizod drugih serij: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Posnetega programa ni bilo mogoče najti."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Sorodni posnetki"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(ni opisa programa)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d posnetek</item>
       <item quantity="two">%1$d posnetka</item>
@@ -362,6 +377,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Ustavitev snemanja serije?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Posnete epizode bodo na voljo v knjižnici digitalnega videorekorderja."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Ustavi"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Trenutno se ne predvaja nobena epizoda."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Na voljo ni nobena epizoda.\nPosnete bodo, ko bodo na voljo."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minuta)</item>
@@ -375,4 +391,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Danes: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Jutri: <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Ocena"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Posneti programi"</string>
 </resources>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
new file mode 100644
index 0000000..17ea800
--- /dev/null
+++ b/res/values-sq-rAL/strings.xml
@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 
+  ~ 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.
+   -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
+    <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
+    <string name="menu_title_play_controls" msgid="2490237359425190652">"Kontrollet e luajtjes"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanalet"</string>
+    <string name="menu_title_options" msgid="7184594626814914022">"Opsionet e televizorit"</string>
+    <string name="play_controls_unavailable" msgid="8900698593131693148">"Kontrollet e luajtjes nuk disponohen për këtë kanal"</string>
+    <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Luaj ose ndërprit"</string>
+    <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Përparo me shpejtësi"</string>
+    <string name="play_controls_description_fast_rewind" msgid="953488122681015803">"Rikthe me shpejtësi"</string>
+    <string name="play_controls_description_skip_next" msgid="1603587562124694592">"Përpara"</string>
+    <string name="play_controls_description_skip_previous" msgid="3858447678278021381">"Prapa"</string>
+    <string name="channels_item_program_guide" msgid="2889807207930678418">"Udhëzuesi i programeve"</string>
+    <string name="channels_item_setup" msgid="6557412175737379022">"Kanale të reja të disponueshme"</string>
+    <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"Hap <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
+    <string name="options_item_closed_caption" msgid="5945274655046367170">"Titrat"</string>
+    <string name="options_item_display_mode" msgid="7989243076748680140">"Modaliteti i ekranit"</string>
+    <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
+    <string name="options_item_multi_audio" msgid="5118851311937896923">"Audioja në shumë gjuhë"</string>
+    <string name="options_item_more_channels" msgid="971040969622943300">"Merr më shumë kanale"</string>
+    <string name="options_item_settings" msgid="7623205838542400074">"Cilësimet"</string>
+    <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Televizori (antena/kablloja)"</string>
+    <string name="no_program_information" msgid="1049844207745145132">"Nuk ka informacione për programin"</string>
+    <string name="program_title_for_no_information" msgid="384451471906070101">"Nuk ka informacione"</string>
+    <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Kanal i bllokuar"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Gjuhë e panjohur"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Titrat %1$d"</string>
+    <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Titrat"</string>
+    <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Joaktive"</string>
+    <string name="closed_caption_system_settings" msgid="1856974607743827178">"Personalizo formatimin"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Cakto preferencat për të gjithë sistemin për titrat"</string>
+    <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Modaliteti i ekranit"</string>
+    <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Audioja në shumë gjuhë"</string>
+    <string name="multi_audio_channel_mono" msgid="6229173848963557723">"mono"</string>
+    <string name="multi_audio_channel_stereo" msgid="3758995659214256587">"stereo"</string>
+    <string name="multi_audio_channel_surround_6" msgid="6066304966228963942">"5.1 rrethues"</string>
+    <string name="multi_audio_channel_surround_8" msgid="2765140653768694313">"7.1 rrethues"</string>
+    <string name="multi_audio_channel_suffix" msgid="4443825738196093772">"%d kanale"</string>
+    <string name="side_panel_title_edit_channels_for_an_input" msgid="7334895164698222989">"Personalizo listën e kanaleve"</string>
+    <string name="edit_channels_item_select_group" msgid="4953000352257999703">"Zgjidh grupin"</string>
+    <string name="edit_channels_item_deselect_group" msgid="5092649099546997807">"Anulo zgjedhjen e grupit"</string>
+    <string name="edit_channels_item_group_by" msgid="7794571851966798199">"Grupo sipas"</string>
+    <string name="edit_channels_group_by_sources" msgid="5481053601210461217">"Burimi i kanalit"</string>
+    <string name="edit_channels_group_by_hd_sd" msgid="5582719665718278819">"HD/SD"</string>
+    <string name="edit_channels_group_divider_for_hd" msgid="5311355566660389423">"HD"</string>
+    <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
+    <string name="side_panel_title_group_by" msgid="1783176601425788939">"Grupo sipas"</string>
+    <string name="program_guide_content_locked" msgid="198056836554559553">"Ky program është bllokuar"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ky program është i pavlerësuar"</string>
+    <string name="program_guide_content_locked_format" msgid="514915272862967389">"Ky program është vlerësuar si <xliff:g id="RATING">%1$s</xliff:g>"</string>
+    <string name="msg_no_setup_activity" msgid="7746893144640239857">"Hyrja nuk e mbështet skanimin automatik"</string>
+    <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Skanimi automatik nuk mund të fillojë për \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
+    <string name="msg_unable_to_start_system_captioning_settings" msgid="705242616044165668">"Preferencat për të gjithë sistemin nuk mund të fillojnë për titrat."</string>
+    <plurals name="msg_channel_added" formatted="false" msgid="5301526166755938705">
+      <item quantity="other">%1$d kanale u shtuan</item>
+      <item quantity="one">%1$d kanal u shtua</item>
+    </plurals>
+    <string name="msg_no_channel_added" msgid="2882586037409921925">"Nuk u shtua asnjë kanal"</string>
+    <string name="menu_parental_controls" msgid="2474294054521345840">"Kontrollet prindërore"</string>
+    <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Aktive"</string>
+    <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Joaktive"</string>
+    <string name="option_channels_locked" msgid="5797855082297549907">"Kanalet u bllokuan"</string>
+    <string name="option_channels_lock_all" msgid="6594512884477342940">"Bllokoji të gjitha"</string>
+    <string name="option_channels_unlock_all" msgid="6839513296447567623">"Zhblloko të gjitha"</string>
+    <string name="option_channels_subheader_hidden" msgid="4669425935426972078">"Kanalet e fshehura"</string>
+    <string name="option_program_restrictions" msgid="241342023067364108">"Kufizimet e programeve"</string>
+    <string name="option_change_pin" msgid="2881594075631152566">"Ndrysho kodin PIN"</string>
+    <string name="option_country_rating_systems" msgid="7288569813945260224">"Sistemet e vlerësimit"</string>
+    <string name="option_ratings" msgid="4009116954188688616">"Vlerësimet"</string>
+    <string name="option_see_all_rating_systems" msgid="7702673500014877288">"Shiko të gjitha sistemet e vlerësimit"</string>
+    <string name="other_countries" msgid="8342216398676184749">"Vende te tjera"</string>
+    <string name="option_no_locked_channel" msgid="2543094883927978444">"Asnjë"</string>
+    <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Asnjë"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"I pavlerësuar"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blloko programet e pavlerësuara"</string>
+    <string name="option_rating_none" msgid="5204552587760414879">"Asnjë"</string>
+    <string name="option_rating_high" msgid="8898400296730158893">"Kufizimet e larta"</string>
+    <string name="option_rating_medium" msgid="6455853836426497151">"Kufizimet mesatare"</string>
+    <string name="option_rating_low" msgid="5800146024503377969">"Kufizimet e ulëta"</string>
+    <string name="option_rating_custom" msgid="3155377834510646436">"I personalizuar"</string>
+    <string name="option_rating_high_description" msgid="609567565273278745">"Përmbajtje e përshtatshme për fëmijët"</string>
+    <string name="option_rating_medium_description" msgid="7169199016608935280">"Përmbajtje e përshtatshme për fëmijë më të rritur"</string>
+    <string name="option_rating_low_description" msgid="4740109576615335045">"Përmbajtje e përshtatshme për adoleshentë"</string>
+    <string name="option_rating_custom_description" msgid="6180723522991233194">"Kufizimet manuale"</string>
+    <string name="option_attribution" msgid="2967657807178951562">"Burimet për përshkrimet e vlerësimeve"</string>
+    <string name="option_subrating_title" msgid="5485055507818077595">"%1$s dhe vlerësimet dytësore"</string>
+    <string name="option_subrating_header" msgid="4637961301549615855">"Vlerësimet dytësore"</string>
+    <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Fut kodin PIN për të parë këtë kanal"</string>
+    <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Fut kodin PIN për të shikuar këtë program"</string>
+    <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Ky program është vlerësuar si <xliff:g id="RATING">%1$s</xliff:g>. Fut kodin PIN për të shikuar këtë program"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Ky program është i pavlerësuar. Fut kodin tënd PIN për të shikuar këtë program"</string>
+    <string name="pin_enter_pin" msgid="249314665028035038">"Fut kodin PIN"</string>
+    <string name="pin_enter_create_pin" msgid="3385754356793309946">"Për të caktuar kontrollet prindërore, krijo një kod PIN"</string>
+    <string name="pin_enter_new_pin" msgid="1739471585849790384">"Fut kodin e ri PIN"</string>
+    <string name="pin_enter_again" msgid="2618999754723090427">"Konfirmo kodin tënd PIN"</string>
+    <string name="pin_enter_old_pin" msgid="4588282612931041919">"Fut kodin PIN aktual"</string>
+    <plurals name="pin_enter_countdown" formatted="false" msgid="3415233538538544309">
+      <item quantity="other">Ke futur kodin e gabuar PIN 5 herë.\nProvo përsëri pas <xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> sekondash.</item>
+      <item quantity="one">Ke futur kodin e gabuar PIN 5 herë.\nProvo përsëri pas <xliff:g id="REMAINING_SECONDS_0">%1$d</xliff:g> sekonde.</item>
+    </plurals>
+    <string name="pin_toast_wrong" msgid="2126295626095048746">"Ai kod PIN ishte i gabuar. Provo përsëri."</string>
+    <string name="pin_toast_not_match" msgid="4283624338659521768">"Provo përsëri, pasi kodi PIN nuk përputhet"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Fut kodin ZIP."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Aplikacioni \"Kanalet drejtpërdrejt\" do të përdorë kodin ZIP për të ofruar një udhëzues të plotë të programeve për kanalet e televizorit."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Fut kodin ZIP"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Kod ZIP i pavlefshëm"</string>
+    <string name="side_panel_title_settings" msgid="8244327316510918755">"Cilësimet"</string>
+    <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Personalizo listën e kanaleve"</string>
+    <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Zgjidh kanalet për udhëzuesin e programeve"</string>
+    <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Burimet e kanaleve"</string>
+    <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Kanale të reja të disponueshme"</string>
+    <string name="settings_parental_controls" msgid="5449397921700749317">"Kontrollet prindërore"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Zhvendosja në kohë"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Regjistro ndërkohë që shikon që të mund t\'i vendosësh në pauzë ose t\'i rikthesh pas programet drejtpërdrejt.\nParalajmërim: Kjo mund të zvogëlojë jetëgjatësinë e hapësirës ruajtëse të brendshme nga përdorimi i lartë i hapësirës ruajtëse."</string>
+    <string name="settings_menu_licenses" msgid="1257646083838406103">"Licencat me burim të hapur"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Dërgo komentet"</string>
+    <string name="settings_menu_version" msgid="2604030372029921403">"Versioni"</string>
+    <string name="tvview_channel_locked" msgid="6486375335718400728">"Për të shikuar këtë kanal, shtyp \"Djathtas\" për të futur kodin tënd PIN"</string>
+    <string name="tvview_content_locked" msgid="391823084917017730">"Për të shikuar këtë program, shtyp \"Djathtas\" për të futur kodin tënd PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Ky program është i pavlerësuar.\nPër të shikuar këtë program, shtyp \"Djathtas\" dhe fut kodin tënd PIN"</string>
+    <string name="tvview_content_locked_format" msgid="3741874636031338247">"Ky program është vlerësuar si <xliff:g id="RATING">%1$s</xliff:g>.\nPër të shikuar këtë program, shtyp \"Djathtas\" dhe fut kodin tënd PIN."</string>
+    <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Për të shikuar këtë kanal, përdor aplikacionin e parazgjedhur të televizionit drejtpërdrejt."</string>
+    <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Për të shikuar këtë program, përdor aplikacionin e parazgjedhur të televizionit drejtpërdrejt."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Ky program është i pavlerësuar.\nPër të shikuar këtë program, përdor aplikacionin e parazgjedhur të televizionit drejtpërdrejt."</string>
+    <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Ky program është vlerësuar si <xliff:g id="RATING">%1$s</xliff:g>.\nPër të shikuar këtë program, përdor aplikacionin e parazgjedhur të televizionit drejtpërdrejt."</string>
+    <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programi është bllokuar"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ky program është i pavlerësuar"</string>
+    <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Ky program është vlerësuar si <xliff:g id="RATING">%1$s</xliff:g>"</string>
+    <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Vetëm audio"</string>
+    <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Sinjal i dobët"</string>
+    <string name="tvview_msg_no_internet_connection" msgid="7655994401188888231">"Nuk ka lidhje interneti"</string>
+    <plurals name="tvview_msg_input_no_resource" formatted="false" msgid="8581894855153658823">
+      <item quantity="other">Ky kanal nuk mund të luhet deri në <xliff:g id="END_TIME_1">%1$s</xliff:g> pasi po regjistrohen kanale të tjera. \n\nShtyp \"Djathtas\" për të rregulluar planifikimin e regjistrimit.</item>
+      <item quantity="one">Ky kanal nuk mund të luhet deri në <xliff:g id="END_TIME_0">%1$s</xliff:g> pasi po regjistrohet një kanal tjetër. \n\nShtyp \"Djathtas\" për të rregulluar planifikimin e regjistrimit.</item>
+    </plurals>
+    <string name="channel_banner_no_title" msgid="8660301979190693176">"Pa titull"</string>
+    <string name="channel_banner_locked_channel_title" msgid="2006564967318945980">"Kanali u bllokua"</string>
+    <string name="setup_category_new" msgid="2899355289563443627">"Të reja"</string>
+    <string name="setup_category_done" msgid="4750902502852212319">"Burimet"</string>
+    <plurals name="setup_input_channels" formatted="false" msgid="1695941684075602971">
+      <item quantity="other">%1$d kanale</item>
+      <item quantity="one">%1$d kanal</item>
+    </plurals>
+    <string name="setup_input_no_channels" msgid="1669327912393163331">"Nuk ka kanale të disponueshme"</string>
+    <string name="setup_input_new" msgid="3337725672277046798">"Të reja"</string>
+    <string name="setup_input_setup_now" msgid="1772000402336958967">"Nuk është konfiguruar"</string>
+    <string name="setup_store_action_title" msgid="4083402039720973414">"Merr burime të tjera"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Shfleto aplikacionet që ofrojnë kanale drejtpërdrejt"</string>
+    <string name="new_sources_title" msgid="3878933676500061895">"Burime të reja të kanaleve të disponueshme"</string>
+    <string name="new_sources_description" msgid="749649005588426813">"Burime të reja të kanaleve kanë kanale për të ofruar.\nKonfiguroji ato tani ose bëje këtë më vonë te cilësimi i burimeve të kanaleve."</string>
+    <string name="new_sources_action_setup" msgid="177693761664016811">"Konfiguro tani"</string>
+    <string name="new_sources_action_skip" msgid="2501296961258184330">"Në rregull, e kuptova"</string>
+    <!-- no translation found for intro_title (251772896916795556) -->
+    <skip />
+    <string name="intro_description" msgid="7806473686446937307"><b>"Shtyp \"ZGJIDH\""</b>" për të pasur qasje te menyja e televizorit."</string>
+    <string name="msg_no_input" msgid="3897674146985427865">"Nuk u gjet asnjë hyrje e televizorit"</string>
+    <string name="msg_no_specific_input" msgid="2688885987104249852">"Hyrja e televizorit nuk mund të gjendet"</string>
+    <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Lloji i sintonizuesit nuk është i përshtatshëm. Hap aplikacionin \"Kanalet drejtpërdrejt\" për hyrjen e televizorit për llojin e sintonizuesit."</string>
+    <string name="msg_tune_failed" msgid="3277419551849972252">"Sintonizimi dështoi"</string>
+    <string name="msg_missing_app" msgid="8291542072400042076">"Nuk u gjet asnjë aplikacion për të menaxhuar këtë veprim"</string>
+    <string name="msg_all_channels_hidden" msgid="777397634062471936">"Të gjitha kanalet e burimit janë të fshehura.\nZgjidh të paktën një kanal për ta shikuar."</string>
+    <string name="msg_channel_unavailable_unknown" msgid="765586450831081871">"Videoja papritur nuk është e disponueshme"</string>
+    <string name="msg_back_key_guide" msgid="7404682718828721924">"Tasti \"PRAPA\" është për pajisjen e lidhur. Shtyp butonin \"KREU\" për të dalë."</string>
+    <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"\"Kanalet drejtpërdrejt\" kanë nevojë për leje për të lexuar listimet e televizorit."</string>
+    <string name="setup_sources_text" msgid="4988039637873759839">"Konfiguro burimet e tua"</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"Kanalet drejtpërdrejt ndërthurin eksperiencën e kanaleve televizive tradicionale me kanalet në transmetim të ofruara nga aplikacionet. \n\nFillo duke konfiguruar burimet e kanaleve të instaluara tashmë. Ose shfleto në \"Dyqanin e Google Play\" për më shumë aplikacione që ofrojnë kanale drejtpërdrejt."</string>
+    <string name="channels_item_dvr" msgid="8911915252648532469">"Regjistrimet dhe planifikimet"</string>
+    <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minuta"</string>
+    <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 minuta"</string>
+    <string name="recording_start_dialog_1_hour_duration" msgid="7159533207022355641">"1 orë"</string>
+    <string name="recording_start_dialog_3_hours_duration" msgid="295984419320006238">"3 orë"</string>
+    <string name="dvr_main_recent" msgid="2553805424822806495">"Të fundit"</string>
+    <string name="dvr_main_scheduled" msgid="7837260963086408492">"Të planifikuara"</string>
+    <string name="dvr_main_series" msgid="8278256687595691676">"Seritë"</string>
+    <string name="dvr_main_others" msgid="2970835573614038153">"Të tjera"</string>
+    <string name="dvr_msg_cannot_record_channel" msgid="6836291367918532447">"Kanali nuk mund të regjistrohet."</string>
+    <string name="dvr_msg_cannot_record_program" msgid="4184046342810946090">"Programi nuk mund të regjistrohet."</string>
+    <string name="dvr_msg_program_scheduled" msgid="3800847542300367572">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> është planifikuar për t\'u regjistruar"</string>
+    <string name="dvr_msg_current_program_scheduled" msgid="2505247201782991463">"Po regjistron <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nga tani deri në <xliff:g id="ENDTIME">%2$s</xliff:g>"</string>
+    <string name="dvr_full_schedule_card_view_title" msgid="7198521806965950089">"Planifikimi i plotë"</string>
+    <plurals name="dvr_full_schedule_card_view_content" formatted="false" msgid="790788122541080768">
+      <item quantity="other">%1$d ditë të tjera</item>
+      <item quantity="one">%1$d ditë tjetër</item>
+    </plurals>
+    <plurals name="dvr_program_duration" formatted="false" msgid="6742119148312354741">
+      <item quantity="other">%1$d minuta</item>
+      <item quantity="one">%1$d minutë</item>
+    </plurals>
+    <plurals name="dvr_count_new_recordings" formatted="false" msgid="3569310208305402815">
+      <item quantity="other">%1$d regjistrime të reja</item>
+      <item quantity="one">%1$d regjistrim i ri</item>
+    </plurals>
+    <plurals name="dvr_count_recordings" formatted="false" msgid="7417379223468131391">
+      <item quantity="other">%1$d regjistrime</item>
+      <item quantity="one">%1$d regjistrim</item>
+    </plurals>
+    <plurals name="dvr_count_scheduled_recordings" formatted="false" msgid="1650330290765214511">
+      <item quantity="other">%1$d regjistrime të planifikuara</item>
+      <item quantity="one">%1$d regjistrim i planifikuar</item>
+    </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Anulo regjistrimin"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Ndalo regjistrimin"</string>
+    <string name="dvr_detail_watch" msgid="7085694764364338215">"Shiko"</string>
+    <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Luaj nga fillimi"</string>
+    <string name="dvr_detail_resume_play" msgid="875591300274416373">"Vazhdo luajtjen"</string>
+    <string name="dvr_detail_delete" msgid="4535881013528321898">"Fshi"</string>
+    <string name="dvr_detail_series_delete" msgid="4831926831670312674">"Fshi regjistrimet"</string>
+    <string name="dvr_detail_series_resume" msgid="6935136228671386246">"Rifillo"</string>
+    <string name="dvr_detail_series_season_title" msgid="5474850936497854790">"Sezoni <xliff:g id="SEASON_NUMBER">%1$s</xliff:g>"</string>
+    <string name="dvr_detail_view_schedule" msgid="7137536927421904426">"Shiko planifikimin"</string>
+    <string name="dvr_detail_read_more" msgid="2588920758094498544">"Lexo më shumë"</string>
+    <string name="dvr_series_deletion_title" msgid="7672649492494507574">"Fshi regjistrimet"</string>
+    <string name="dvr_series_deletion_description" msgid="994839237906552969">"Zgjidh episodet që dëshiron të fshish. Ato nuk mund të rikuperohen pasi të fshihen."</string>
+    <string name="dvr_series_deletion_no_recordings" msgid="481210819034514">"Nuk ka regjistrime për të fshirë."</string>
+    <string name="dvr_series_select_watched" msgid="3608122404146716502">"Zgjidh episodet e shikuara"</string>
+    <string name="dvr_series_select_all" msgid="5415749261739544048">"Zgjidh të gjitha episodet"</string>
+    <string name="dvr_series_deselect_all" msgid="1680395960166387572">"Anulo zgjedhjen për të gjitha episodet"</string>
+    <string name="dvr_series_watched_info_minutes" msgid="5656926431901526030">"<xliff:g id="WATCHED">%1$d</xliff:g> nga <xliff:g id="DURATION">%2$d</xliff:g> minuta të shikuara"</string>
+    <string name="dvr_series_watched_info_seconds" msgid="2667537184197566662">"<xliff:g id="WATCHED">%1$d</xliff:g> nga <xliff:g id="DURATION">%2$d</xliff:g> sekonda të shikuara"</string>
+    <string name="dvr_series_never_watched" msgid="6086008065876122655">"Asnjëherë të shikuara"</string>
+    <plurals name="dvr_msg_episodes_deleted" formatted="false" msgid="5627112959798353905">
+      <item quantity="other">%1$d nga %2$d episode janë fshirë</item>
+      <item quantity="one">%1$d nga %2$d episod është fshirë</item>
+    </plurals>
+    <string name="dvr_series_settings_priority" msgid="5836437092774185710">"Me prioritet"</string>
+    <string name="dvr_series_settings_priority_highest" msgid="1072006447796648382">"Maksimal"</string>
+    <string name="dvr_series_settings_priority_lowest" msgid="6003996497908810225">"Shumë të ulët"</string>
+    <string name="dvr_series_settings_priority_rank" msgid="667778382820956116">"Numri <xliff:g id="RANK">%1$d</xliff:g>"</string>
+    <string name="dvr_series_settings_channels" msgid="3164900110165729909">"Kanalet"</string>
+    <string name="dvr_series_settings_channels_all" msgid="656434955168572976">"Çdo kanal"</string>
+    <string name="dvr_priority_title" msgid="1537886929061487213">"Zgjidh përparësinë"</string>
+    <string name="dvr_priority_description" msgid="8362040921417154645">"Kur ka shumë programe për t\'u regjistruar në të njëjtën kohë, vetëm ata me përparësitë më të larta do të regjistrohen."</string>
+    <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Ruaj"</string>
+    <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Regjistrimet e njëhershme kanë përparësinë më të lartë"</string>
+    <string name="dvr_action_stop" msgid="1378723485295471381">"Ndalo"</string>
+    <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Shiko planifikimin e regjistrimeve"</string>
+    <string name="dvr_action_record_episode" msgid="8596182676610326327">"Vetëm këtë regjistrim"</string>
+    <string name="dvr_action_record_episode_from_now_description" msgid="5125122951529985697">"tani - <xliff:g id="ENDTIME">%1$s</xliff:g>"</string>
+    <string name="dvr_action_record_series" msgid="8501991316179436899">"Të gjithë serinë…"</string>
+    <string name="dvr_action_record_anyway" msgid="991470058034937231">"Planifiko gjithsesi"</string>
+    <string name="dvr_action_record_instead" msgid="6821164728752215738">"Regjistro këtë më mirë"</string>
+    <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Anuloje këtë regjistrim"</string>
+    <string name="dvr_action_watch_now" msgid="7181211920959075976">"Shiko tani"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Fshi regjistrimet…"</string>
+    <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Mund të regjistrohet"</string>
+    <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Regjistrimi u planifikua"</string>
+    <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Konflikt në regjistrim"</string>
+    <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Regjistrimi"</string>
+    <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Regjistrimi dështoi"</string>
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Po lexon programet"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Shiko regjistrimet e fundit"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Regjistrimi i <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nuk është i plotë."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Regjistrimet e <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> dhe <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nuk janë të plota."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Regjistrimet e <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> dhe <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nuk janë të plota."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Regjistrimi i <xliff:g id="PROGRAMNAME">%1$s</xliff:g> nuk përfundoi për shkak të hapësirës ruajtëse të pamjaftueshme."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Regjistrimet e <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> dhe <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> nuk përfunduan për shkak të hapësirës ruajtëse të pamjaftueshme."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Regjistrimet e <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> dhe <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> nuk përfunduan për shkak të hapësirës ruajtëse të pamjaftueshme."</string>
+    <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR-ja ka nevojë për më shumë hapësirë ruajtëse"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Do të mund t\'i regjistrosh programet me DVR. Sidoqoftë, nuk ka hapësirë ruajtëse të mjaftueshme në pajisje tani që DVR-ja të funksionojë. Lidh një njësi të jashtme disku që është <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB ose më shumë dhe ndiq hapat për ta formatuar si hapësirë ruajtëse të pajisjes."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Nuk ka hapësirë ruajtëse të mjaftueshme"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Ky program nuk do të regjistrohet pasi nuk ka hapësirë ruajtëse të mjaftueshme. Provo të fshish disa regjistrime ekzistuese."</string>
+    <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Hapësira ruajtëse mungon"</string>
+    <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Të ndalohet regjistrimi?"</string>
+    <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Përmbajtja e regjistruar do të ruhet."</string>
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Regjistrimi i <xliff:g id="PROGRAMNAME">%1$s</xliff:g> do të ndalohet pasi është në konflikt me këtë program. Përmbajtja e regjistruar do të ruhet."</string>
+    <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Regjistrimi u planifikua, por ka konflikte"</string>
+    <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Regjistrimi ka nisur, por ka konflikte"</string>
+    <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> do të regjistrohet."</string>
+    <string name="dvr_channel_conflict_dialog_description_prefix" msgid="212344250779878791">"<xliff:g id="CHANNELNAME">%1$s</xliff:g> po regjistrohet."</string>
+    <string name="dvr_program_conflict_dialog_description_1" msgid="2278200346765501164">"Disa pjesë të <xliff:g id="CONFLICTPROGRAMNAME">%1$s</xliff:g> nuk do të regjistrohen."</string>
+    <string name="dvr_program_conflict_dialog_description_2" msgid="5648524408147235696">"Disa pjesë të <xliff:g id="CONFLICTPROGRAMNAME_1">%1$s</xliff:g> dhe <xliff:g id="CONFLICTPROGRAMNAME_2">%2$s</xliff:g> nuk do të regjistrohen."</string>
+    <string name="dvr_program_conflict_dialog_description_3" msgid="6879199850098595108">"Disa pjesë të <xliff:g id="CONFLICTPROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2">%2$s</xliff:g> dhe një regjistrimi tjetër nuk do të regjistrohen."</string>
+    <plurals name="dvr_program_conflict_dialog_description_many" formatted="false" msgid="1008340710252647947">
+      <item quantity="other">Disa pjesë të <xliff:g id="CONFLICTPROGRAMNAME_1_2">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_3">%2$s</xliff:g> dhe %3$d planifikime të tjera nuk do të regjistrohen.</item>
+      <item quantity="one">Disa pjesë të <xliff:g id="CONFLICTPROGRAMNAME_1_0">%1$s</xliff:g>, <xliff:g id="CONFLICTPROGRAMNAME_2_1">%2$s</xliff:g> dhe %3$d planifikim tjetër nuk do të regjistrohen.</item>
+    </plurals>
+    <string name="dvr_schedule_dialog_title" msgid="5235629824986156058">"Çfarë dëshiron të regjistrosh?"</string>
+    <string name="dvr_channel_record_duration_dialog_title" msgid="4601361040431047918">"Për sa kohë dëshiron të regjistrosh?"</string>
+    <string name="dvr_already_scheduled_dialog_title" msgid="4525318291210934311">"Planifikuar tashmë"</string>
+    <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"I njëjti program është planifikuar tashmë që të regjistrohet në <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
+    <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Regjistruar tashmë"</string>
+    <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Ky program është regjistruar tashmë. Ai disponohet në bibliotekën DVR."</string>
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Regjistrimi i serisë u planifikua"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> regjistrime janë planifikuar për <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> regjistrim është planifikuar për <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> regjistrime janë planifikuar për <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> prej tyre nuk do të regjistrohen për shkak të konflikteve.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> regjistrim është planifikuar për <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Ai nuk do të regjistrohet për shkak të konflikteve.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> regjistrime janë planifikuar për <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episode të kësaj serie dhe serive të tjera nuk do të regjistrohen për shkak të konflikteve.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> regjistrim është planifikuar për <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episode të kësaj serie dhe serive të tjera nuk do të regjistrohen për shkak të konflikteve.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> regjistrime janë planifikuar për <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episod i serive të tjera nuk do të regjistrohet për shkak të konflikteve.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> regjistrim është planifikuar për <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 episod i serive të tjera nuk do të regjistrohet për shkak të konflikteve.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> regjistrime janë planifikuar për <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episode të serive të tjera nuk do të regjistrohen për shkak të konflikteve.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> regjistrim është planifikuar për <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> episode të serive të tjera nuk do të regjistrohen për shkak të konflikteve.</item>
+    </plurals>
+    <string name="dvr_program_not_found" msgid="3282879532038010202">"Programi i regjistruar nuk u gjet."</string>
+    <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Regjistrimet e lidhura"</string>
+    <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
+      <item quantity="other">%1$d regjistrime</item>
+      <item quantity="one">%1$d regjistrim</item>
+    </plurals>
+    <string name="dvr_schedules_information_separator" msgid="1669116853379998479">" / "</string>
+    <string name="dvr_schedules_deletion_info" msgid="2837586459900271031">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> u hoq nga planifikimi i regjistrimeve"</string>
+    <string name="dvr_schedules_tuner_conflict_will_be_partially_recorded" msgid="5280490298546908729">"Do të regjistrohet pjesërisht për shkak të konflikteve të sintonizuesit."</string>
+    <string name="dvr_schedules_tuner_conflict_will_not_be_recorded_info" msgid="5065400564003201095">"Nuk do të regjistrohet për shkak të konflikteve të sintonizuesit."</string>
+    <string name="dvr_schedules_empty_state" msgid="1291529283469462741">"Nuk ka asnjë regjistrim ende të planifikim.\nMund ta planifikosh regjistrimin nga udhëzuesi i programeve."</string>
+    <plurals name="dvr_series_schedules_header_description" formatted="false" msgid="9077188267856194114">
+      <item quantity="other">%1$d konflikte regjistrimi</item>
+      <item quantity="one">%1$d konflikt regjistrimi</item>
+    </plurals>
+    <string name="dvr_series_schedules_settings" msgid="4868501926847903985">"Cilësimet e serive"</string>
+    <string name="dvr_series_schedules_start" msgid="8458768834047133835">"Nis regjistrimin e serisë"</string>
+    <string name="dvr_series_schedules_stop" msgid="3427479298317584961">"Ndalo regjistrimin e serisë"</string>
+    <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Të ndalohet regjistrimi i serisë?"</string>
+    <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Episodet e regjistruara do të jenë të disponueshme në bibliotekën DVR."</string>
+    <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Ndalo"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Nuk ka episode në transmetim tani."</string>
+    <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Nuk ka episode të disponueshme.\nAto do të regjistrohen pasi të jenë të disponueshme."</string>
+    <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
+      <item quantity="other">(%1$d minuta)</item>
+      <item quantity="one">(%1$d minutë) </item>
+    </plurals>
+    <string name="dvr_date_today" msgid="7691050705354303471">"Sot"</string>
+    <string name="dvr_date_tomorrow" msgid="4136735681186981844">"Nesër"</string>
+    <string name="dvr_date_yesterday" msgid="2127672919053118239">"Dje"</string>
+    <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> sot"</string>
+    <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> nesër"</string>
+    <string name="program_guide_critic_score" msgid="340530743913585150">"Rezultati"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Programet e regjistruara"</string>
+</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 0b4c2f3..ce291ed 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"моно"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"стерео"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Play контроле"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Недавни канали"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Канали"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"ТВ опције"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Опц. сл. у сл."</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Контроле за пуштање нису доступне за овај канал"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Пусти или паузирај"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Премотај унапред"</string>
@@ -35,36 +34,18 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Титлови"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Режим приказа"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"Слика у слици"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Укључено"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Искључено"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Вишеструк аудио"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Набави још канала"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Подешавања"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Извор"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Замени"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Укључено"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Искључено"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Звук"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Главни"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Прозор слике у слици"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Распоред"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Доњи десни угао"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Горњи десни угао"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Горњи леви угао"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Доњи леви угао"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Упоредо"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Величина"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Велика"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Мала"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Извор улаза"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ТВ (антенска/кабловска)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Нема информација о програму"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Нема информација"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Блокирани канал"</string>
-    <string name="default_language" msgid="4122326459624337928">"Непознат језик"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Непознат језик"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Опционални титл: %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Опционални титлови"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Искључи"</string>
-    <string name="closed_caption_system_settings" msgid="1856974607743827178">"Прилагоди формат"</string>
+    <string name="closed_caption_system_settings" msgid="1856974607743827178">"Прилагођавање формата"</string>
     <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"Изаберите подешавања титлова за цео систем"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Режим приказа"</string>
     <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Вишеструки аудио"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Групиши према"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Овај програм је блокиран"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Овај програм није оцењен"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Овај програм има оцену <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Улаз не подржава аутоматско скенирање"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Није успело покретање аутоматског скенирања за „<xliff:g id="TV_INPUT">%s</xliff:g>“"</string>
@@ -93,7 +75,6 @@
       <item quantity="other">Додато је %1$d канала</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Нема додатих канала"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Тјунер"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Родитељски надзор"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Укључи"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Искључи"</string>
@@ -109,6 +90,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Друге земље"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Ништа"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Ништа"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Неоцењено"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Блокирај неоцењене програме"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Ништа"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Велика ограничења"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Средња ограничења"</string>
@@ -125,6 +108,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Унесите PIN да бисте гледали овај канал"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Унесите PIN да бисте гледали овај програм"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Овај програм има оцену <xliff:g id="RATING">%1$s</xliff:g>. Унесите PIN да бисте гледали овај програм"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Овај програм није оцењен. Унесите PIN да бисте гледали овај програм"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Унесите PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Да бисте подесили родитељску контролу, направите PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Унесите нови PIN"</string>
@@ -137,22 +121,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Тај PIN је погрешан. Пробајте поново."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Пробајте поново, PIN се не подудара"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Унесите поштански број"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Апликација Канали уживо ће користити овај поштански број да би пружила комплетан водич за програме за ТВ канале."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Унесите поштански број"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Неважећи поштански број"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Подешавања"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Прилагоди листу канала"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Изаберите канале за водич за програме"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Извори канала"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Доступни су нови канали"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Родитељски надзор"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Контрола времена"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Снимајте док гледате да бисте могли да паузирате или премотате програме уживо.\nУпозорење: Ово може да скрати радни век интерне меморије због њеног интензивног коришћења."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Лиценце отвореног кода"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Лиценце отвореног кода"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Пошаљи повратне информације"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Верзија"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Да бисте гледали овај канал, притисните дугме Десно и унесите PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Да бисте гледали овај програм, притисните дугме Десно и унесите PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Овај програм није оцењен.\nДа бисте гледали овај програм, притисните тастер са стрелицом удесно и унесите PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Овај програм има оцену <xliff:g id="RATING">%1$s</xliff:g>.\nДа бисте гледали овај програм, притисните дугме Десно и унесите PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Да бисте гледали овај канал, користите подразумевану апликацију за ТВ уживо."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Да бисте гледали овај програм, користите подразумевану апликацију за ТВ уживо."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Овај програм није оцењен.\nTДа бисте гледали овај програм, користите подразумевану апликацију за ТВ уживо."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Овај програм има оцену <xliff:g id="RATING">%1$s</xliff:g>.\nДа бисте гледали овај програм, користите подразумевану апликацију за ТВ уживо."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Програм је блокиран"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Овај програм није оцењен"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Овај програм има оцену <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Само аудио"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Слаб сигнал"</string>
@@ -185,8 +178,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Притисните ИЗАБЕРИ"</b>" да бисте приступили TV менију."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Нису пронађени ТВ улази"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Не можемо да пронађемо ТВ улаз"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Слика у слици није подржана"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Нема улаза који може да се прикаже као слика у слици"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Тип тјунера не одговара. Покрените апликацију Канали уживо за тип ТВ улаза са тјунером."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Подешавање није успело"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Није пронађена ниједна апликација која би могла да обави ову радњу."</string>
@@ -235,6 +226,8 @@
       <item quantity="few">%1$d снимања су заказана</item>
       <item quantity="other">%1$d снимања је заказано</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Откажи снимање"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Заустави снимање"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Пусти"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Пусти од почетка"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Настави репродукцију"</string>
@@ -268,9 +261,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Када истовремено има превише програма за снимање, снимаће се само програми са вишим приоритетом."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Сачувај"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Једнократни снимци имају највиши приоритет"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Откажи"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Откажи"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Заборави"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Заустави"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Прикажи распоред за снимање"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Само ова епизода"</string>
@@ -280,25 +270,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Сними овај програм уместо њега"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Откажи ово снимање"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Пусти одмах"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Избришите снимке…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Подржава снимање"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Снимање је заказано"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Неусаглашеност при снимању"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Снимање"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Снимање није успело"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Читамо програме да бисмо направили распореде"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Читамо програме"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Читамо програме"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Прикажи недавне снимке"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Снимање програма <xliff:g id="PROGRAMNAME">%1$s</xliff:g> није довршено."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Снимање програма <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> и <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> није довршено."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Снимање програма <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> и <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> није довршено."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Нисмо довршили снимање програма <xliff:g id="PROGRAMNAME">%1$s</xliff:g> због недовољног меморијског простора."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Снимање програма <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> и <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> није довршено због недовољног меморијског простора."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Снимање програма <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> и <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> није довршено због недовољног меморијског простора."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR-у треба више меморијског простора"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Моћи ћете да снимате програме помоћу DVR-а. Међутим, тренутно на уређају нема довољно меморијског простора да би DVR функционисао. Повежите спољни диск који има <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB или више и пратите кораке да бисте га форматирали као меморијски простор уређаја."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Моћи ћете да снимате програме помоћу DVR-а. Међутим, тренутно на уређају нема довољно меморијског простора да би DVR функционисао. Повежите спољни диск који има <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB или више и пратите кораке да бисте га форматирали као меморијски простор уређаја."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Нема довољно меморијског простора"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Овај програм неће бити снимљен јер нема довољно меморијског простора. Пробајте да избришете неколико постојећих снимака."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Меморијски простор недостаје"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Недостаје део меморијског простора који DVR користи. Повежите спољни диск који сте раније користили да бисте поново омогућили DVR. Уместо тога можете да заборавите меморијски простор ако више није доступан."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Желите ли да заборавите меморијски простор?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Сав снимљени садржај и распореди ће бити изгубљени."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Зауставити снимање?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Снимљени садржај ће се сачувати."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Снимање програма <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ће се зауставити јер је дошло до неусаглашености са овим програмом. Снимљени садржај ће бити сачуван."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Снимање је заказано, али постоје неусаглашености"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Снимање је почело али има неусаглашености"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Програм <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ће бити снимљен."</string>
@@ -317,17 +310,34 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Снимање истог програма је већ заказано за <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Већ је снимљено"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Овај програм је већ снимљен. Доступан је у DVR филмотеци."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Снимање серије је заказано"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимање је заказано за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања су заказана за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања је заказано за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимање је заказано за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Због преклапања неће бити снимљено: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања су заказана за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Због преклапања неће бити снимљено: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања је заказано за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Због преклапања неће бити снимљено: <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимање је заказано за серијал <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизода(е) овог серијала и других серијала неће бити снимљено због преклапања.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимања су заказана за серијал <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизода(е) овог серијала и других серијала неће бити снимљено због преклапања.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимања је заказано за серијал <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизода(е) овог серијала и других серијала неће бити снимљено због преклапања.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимање је заказано за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 епизода другог серијала неће бити снимљена због преклапања.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања су заказана за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 епизода другог серијала неће бити снимљена због преклапања.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> снимања је заказано за серијал <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 епизода другог серијала неће бити снимљена због преклапања.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимање је заказано за серијал <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизоде(а) других серијала неће бити снимљено због преклапања.</item>
+      <item quantity="few"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимања су заказана за серијал <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизоде(а) других серијала неће бити снимљено због преклапања.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> снимања је заказано за серијал <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> епизоде(а) других серијала неће бити снимљено због преклапања.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Снимљени програм није пронађен."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Сродни снимци"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Нема описа програма)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d снимак</item>
       <item quantity="few">%1$d снимка</item>
@@ -349,6 +359,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Зауставити снимање серије?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Снимљене епизоде ће остати доступне у DVR библиотеци."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Заустави"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Тренутно се не приказује ниједна епизода."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Нема доступних епизода.\nБиће снимљене када постану доступне."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d минут)</item>
@@ -361,4 +372,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Данас <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Сутра <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Оцена"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Снимљене емисије"</string>
 </resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 212fd95..62bbe7f 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Uppspelningskontroller"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Senaste kanaler"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanaler"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Tv-alternativ"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP-alternativ"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Uppspelningskontrollerna är inte tillgängliga för den här kanalen"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Spela upp eller pausa"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Snabbspola framåt"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Textning"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Visningsläge"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"På"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Av"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Flera ljudkäll."</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Få fler kanaler"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Inställningar"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Källa"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Byt"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"På"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Av"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Ljud"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Primär"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP-fönster"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Nere till h."</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Uppe till h."</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Uppe till v."</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Nere till v."</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Sida vid sida"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Storlek"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Stor"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Liten"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Ingångskälla"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Tv (antenn/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Ingen programinformation"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Ingen information"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Blockerad kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Okänt språk"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Okänt språk"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Textning %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Textning"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Av"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Anpassa formatering"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Ordna efter"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Programmet är blockerat"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Det här programmet har ingen åldersgräns"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Det här programmet har kategoriserats som <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Ingången stöder inte automatisk sökning"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Det går inte att starta automatisk sökning för <xliff:g id="TV_INPUT">%s</xliff:g>"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d kanal har lagts till</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Inga kanaler har lagts till"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Mottagare"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Barnfilter"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"På"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Av"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Övriga länder"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Inga"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Inga"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Ingen åldersgräns"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Blockera prog. utan åldersgr."</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Inga"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Höga begränsningar"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Medelbegränsningar"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Ange pinkoden om du vill titta på den här kanalen"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Ange pinkoden om du vill titta på det här programmet"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Programmet har klassificerats som <xliff:g id="RATING">%1$s</xliff:g>. Ange pinkoden om du vill titta på programmet"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Det här programmet har ingen åldersgräns. Ange pinkoden om du vill titta på programmet"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Ange din pinkod"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Skapa en pinkod om du vill konfigurera barnfiltret"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Ange en ny pinkod"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Det var fel pinkod. Försök igen."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Försök igen. Pinkoden stämmer inte"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Ange ditt postnummer."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Appen Livekanaler använder postnumret till att ta fram en komplett programguide för TV-kanalerna."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Ange ditt postnummer"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Ogiltigt postnummer"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Inställningar"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Anpassa kanallista"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Välj kanaler för programguiden"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanalkällor"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Det finns nya kanaler"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Innehållsfilter"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Tidsförskjutning"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Spela in medan du tittar så att du kan pausa och spola tillbaka program medan de sänds.\nVarning! Detta kan medföra att internminnets livslängd förkortas eftersom lagringsutrymmet används mycket."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Licenser för öppen källkod"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Öppen källkod"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Skicka feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Version"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Tryck till höger och ange pinkoden om du vill titta på den här kanalen"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Tryck till höger och ange pinkoden om du vill titta på det här programmet"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Det här programmet har ingen åldersgräns.\nOm du vill titta på programmet trycker du på Höger och anger pinkoden."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Det här programmet har kategoriserats som <xliff:g id="RATING">%1$s</xliff:g>\nTryck till höger och ange pinkoden om du vill titta på det här programmet."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Använd standardappen för live-TV om du vill titta på den här kanalen."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Använd standardappen för live-TV om du vill titta på programmet."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Det här programmet har ingen åldersgräns.\nAnvänd standardappen för direktsänd TV om du vill titta på programmet."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Programmet har klassificeringen <xliff:g id="RATING">%1$s</xliff:g>.\nAnvänd standardappen för live-TV om du vill titta på programmet."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Programmet har blockerats"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Det här programmet har ingen åldersgräns"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Det här programmet har kategoriserats som <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Endast ljud"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Svag signal"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Tryck på VÄLJ"</b>" för att öppna TV-menyn."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Ingen tv-ingång hittades"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Det går inte att hitta tv-ingången"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP stöds inte"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Det finns ingen tillgänglig ingång som kan visas med PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Olämplig insignal. Starta appen Livekanaler om du vill kunna ta emot insignaler av tv-kortstyp."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Kanaljusteringen misslyckades"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Ingen app som kan hantera åtgärden hittades"</string>
@@ -191,11 +182,11 @@
     <string name="msg_back_key_guide" msgid="7404682718828721924">"Knappen BACK (bakåt) gäller en ansluten enhet. Avsluta genom att trycka på knappen HOME (start)."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Livekanaler behöver behörighet att läsa TV-tablåer."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Konfigurera dina källor"</string>
-    <string name="setup_sources_description" msgid="5695518946225445202">"Livekanaler kombinerar det bästa från traditionella TV-kanaler med strömmande kanaler från appar. \n\nKom igång genom att konfigurera de kanalkällor som redan är installerade eller kolla in Google Play Butik för fler appar som erbjuder livekanaler."</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"Livekanaler kombinerar det bästa från traditionella TV-kanaler med streamade kanaler från appar. \n\nKom igång genom att konfigurera de kanalkällor som redan är installerade eller kolla in Google Play Butik för fler appar som erbjuder livekanaler."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Inspelningar och scheman"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 minuter"</string>
     <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 minuter"</string>
-    <string name="recording_start_dialog_1_hour_duration" msgid="7159533207022355641">"En timme"</string>
+    <string name="recording_start_dialog_1_hour_duration" msgid="7159533207022355641">"1 timme"</string>
     <string name="recording_start_dialog_3_hours_duration" msgid="295984419320006238">"3 timmar"</string>
     <string name="dvr_main_recent" msgid="2553805424822806495">"Senaste"</string>
     <string name="dvr_main_scheduled" msgid="7837260963086408492">"Planerat"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d schemalagda inspelningar</item>
       <item quantity="one">%1$d schemalagd inspelning</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Avbryt inspelning"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Sluta spela in"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Klocka"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Spela upp från början"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Fortsätt spela upp"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"När det finns för många program för att de ska kunna spelas in samtidigt spelas endast de med högst prioritet in."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Spara"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Engångsinspelningar har högsta prioritet"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Avbryt"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Avbryt"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Glöm"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Stoppa"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Visa inspelningsschema"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Bara det här programmet"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Spela in detta i stället"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Avbryt den här inspelningen"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Titta nu"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Radera inspelningar …"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Kan spelas in"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Inspelningen har schemalagts"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Inspelningskonflikt"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Inspelning"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Inspelningen misslyckades"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Läser in program för att inspelningsscheman"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Läser in program"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Läser in program"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Visa de senaste inspelningarna"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Inspelningen av <xliff:g id="PROGRAMNAME">%1$s</xliff:g> är ofullständig."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Inspelningen av <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> och <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> är ofullständig."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Inspelningen av <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> och <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> är ofullständig."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Det gick inte att slutföra inspelningen av <xliff:g id="PROGRAMNAME">%1$s</xliff:g> eftersom det inte finns tillräckligt med lagringsutrymme."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Det gick inte att slutföra inspelningen av <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> och <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> eftersom det inte finns tillräckligt med lagringsutrymme."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Det gick inte att slutföra inspelningen av <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> och <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> eftersom det inte finns tillräckligt med lagringsutrymme."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Mer lagringsutrymme krävs för hårddiskinspelning"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Du kan använda hårddiskinspelning för att spela in program, men just nu finns det inte tillräckligt mycket ledigt lagringsutrymme på enheten för hårddiskinspelning. Anslut en extern enhet på minst <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB och följ anvisningarna för att formatera den som enhetslagring."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Du kan använda hårddiskinspelning för att spela in program, men just nu finns det inte tillräckligt mycket ledigt lagringsutrymme på enheten för hårddiskinspelning. Anslut en extern enhet på minst <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB och följ anvisningarna för att formatera den som enhetslagring."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Otillräckligt lagringsutrymme"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Det här programmet spelas inte in eftersom lagringsutrymmet inte räcker. Du kan göra plats genom att radera gamla inspelningar."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Lagringsutrymmet är inte tillgängligt"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"En del av lagringsutrymmet som används av DVR saknas. Anslut den externa hårddisken du använde innan DVR återaktiverades. Du kan också att välja att glömma bort lagringsutrymmet om det inte längre är tillgängligt."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Ska lagringsutrymmet glömmas bort?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Allt rekommenderat innehåll och alla inspelningsscheman försvinner."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Vill du sluta spela in?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Det inspelade innehållet sparas."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Inspelningen av <xliff:g id="PROGRAMNAME">%1$s</xliff:g> avbryts eftersom den krockar med det här programmet. Det inspelade innehållet sparas."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Inspelningen har schemalagts men innehåller konflikter"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Inspelningen har startat men innehåller konflikter"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> spelas in."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Samma program har schemalagts för inspelning kl. <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Redan inspelat"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Programmet har redan spelats in. Det finns i DVR-biblioteket."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Serieinspelningen har schemalagts"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> inspelningar har schemalagts för <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> inspelning har schemalagts för <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> inspelningar har schemalagts för <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> av dem spelas inte in på grund av programkrockar.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> inspelning har schemalagts för <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Det spelas inte in på grund av programkrockar.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> inspelningar har schemalagts för <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> avsnitt av den här serien och andra serier spelas inte in på grund av programkrockar.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> inspelning har schemalagts för <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> avsnitt av den här serien och andra serier spelas inte in på grund av programkrockar.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> inspelningar har schemalagts för <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 avsnitt av andra serier spelas inte in på grund av programkrockar.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> inspelning har schemalagts för <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 avsnitt av andra serier spelas inte in på grund av programkrockar.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> inspelningar har schemalagts för <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> avsnitt av andra serier spelas inte in på grund av programkrockar.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> inspelning har schemalagts för <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> avsnitt av andra serier spelas inte in på grund av programkrockar.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Det gick inte att hitta det inspelade programmet."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Relaterade inspelningar"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Programbeskrivning saknas)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d inspelningar</item>
       <item quantity="one">%1$d inspelning</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Vill du stoppa serieinspelning?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Inspelade avsnitt finns kvar i DVR-biblioteket"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Stoppa"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Inga avsnitt sänds just nu."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Det finns inga tillgängliga avsnitt.\nDe spelas in när de är tillgängliga."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d minuter)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> i dag"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> i morgon"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Betyg"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Inspelade program"</string>
 </resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 00038ff..ac55f0a 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Vidhibiti vya kucheza"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Vituo vya hivi karibuni"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Vituo"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Chaguo za Runinga"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Chaguo za PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Vidhibiti vya kucheza havipatikani kwa kituo hiki"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Cheza au usitishe"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Peleka mbele kwa kasi"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Manukuu"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Hali ya onyesho"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Imewashwa"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Imezimwa"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Sauti nyingi"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Pata vituo zaidi"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Mipangilio"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Chanzo"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Badili"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Imewashwa"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Imezimwa"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Sauti"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Kuu"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Dirisha la PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Muundo"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Chini kulia"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Juu kulia"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Juu kushoto"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Chini kushoto"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Upande kwa upande"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Ukubwa"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Kubwa"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Ndogo"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Chanzo cha data"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"Runinga (antena/kebo)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Hakuna maelezo ya programu"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Hakuna maelezo"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Kituo kilichozuiwa"</string>
-    <string name="default_language" msgid="4122326459624337928">"Lugha Isiyojulikana"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Lugha isiyojulikana"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Manukuu %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Manukuu"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Imezimwa"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Geuza muundo ukufae"</string>
@@ -83,16 +64,16 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Panga kikundi kwa"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Kipindi hiki kimezuiwa"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Kipindi hiki hakijakadiriwa"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Kipindi hiki kimekadiriwa <xliff:g id="RATING">%1$s</xliff:g>"</string>
-    <string name="msg_no_setup_activity" msgid="7746893144640239857">"Kifaa cha kuingiza sauti hakitumii uchanganuzi wa kiotomatiki"</string>
-    <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Haikuweza kuanzisha uchanganuzi kiotomatiki kwa \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
+    <string name="msg_no_setup_activity" msgid="7746893144640239857">"Kifaa cha kuingiza sauti hakitumii ukaguzi wa kiotomatiki"</string>
+    <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Haikuweza kuanzisha ukaguzi wa kiotomatiki wa \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
     <string name="msg_unable_to_start_system_captioning_settings" msgid="705242616044165668">"Haikuweza kuanzisha mapendeleo ya mfumo mzima kwa manukuu."</string>
     <plurals name="msg_channel_added" formatted="false" msgid="5301526166755938705">
       <item quantity="other">Vituo %1$d vimeongezwa</item>
       <item quantity="one">Kituo %1$d kimeongezwa </item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Hakuna vituo vimeongezwa"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Kirekebisha mawimbi"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Udhibiti wa wazazi"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Imewashwa"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Imezimwa"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Nchi nyingine"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Hakuna"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Hakuna"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Hakijakadiriwa"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Zuia vipindi ambavyo havijakadiriwa"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Hakuna"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Vizuizi kiwango cha juu"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Vikwazo vya kati"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Weka PIN yako ili uangalie kituo hiki"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Weka PIN yako ili uangalie kipindi hiki"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Kipindi hiki kimepewa ukadiriaji wa <xliff:g id="RATING">%1$s</xliff:g>. Weka PIN yako ili ukitazame"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Kipindi hiki hakijakadiriwa. Andika PIN yako ili ukitazame"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Weka PIN yako"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Ili uweke udhibiti wa wazazi, unda PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Weka PIN mpya"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN uliyoweka si sahihi. Jaribu tena."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Jaribu tena, PIN hailingani"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Andika Msimbo wa Eneo lako"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Programu ya Televisheni Mtandaoni itatumia Msimbo wa eneo lako ili kutoa orodha kamili ya vipindi vya vituo vya televisheni."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Weka Msimbo wa Eneo lako"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Msimbo wa Eneo si Sahihi"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Mipangilio"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Geuza orodha ya vituo utakavyo"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Chagua vituo kwa ajili ya orodha yako ya vipindi"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Vyanzo vya vituo"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Vituo vipya vinapatikana"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Udhibiti wa wazazi"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Kipengele cha kubadilisha wakati"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Rekodi vipindi vinapoendelea kucheza ili uweze kusitisha au kurudisha nyuma vipindi vya moja kwa moja.\nOnyo: Huenda hatua hii ikapunguza muda wa matumizi ya hifadhi ya ndani kutokana na matumizi mengi ya hifadhi."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Leseni za programu huria"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Leseni za programu huria"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Tuma maoni"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Toleo"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Ili uangalie kituo hiki, bonyeza Kulia na uweke PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Ili uangalie kipindi hiki, bonyeza Kulia na uweke PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Kipindi hiki hakijakadiriwa.\nIli ukitazame, bofya \'Sawa\' kisha uandike PIN yako"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Kipindi hiki kimekadiriwa <xliff:g id="RATING">%1$s</xliff:g>.\nIli utazame kipindi hiki, bonyeza Kulia na uweke PIN yako"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Ili kutazama kituo hiki, tumia chaguo-msingi ya programu ya TV ya moja kwa moja."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Ili kutazama kituo hiki, tumia chaguo-msingi ya programu ya TV ya moja kwa moja."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Kipindi hiki hakijakadiriwa.\nIli ukitazame, tumia programu chaguo-msingi ya Televisheni ya Moja kwa Moja."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Programu hii imekadiriwa <xliff:g id="RATING">%1$s</xliff:g>.\nIli kutazama kituo hiki, tumia chaguo-msingi ya programu ya TV ya moja kwa moja."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Kipindi kimezuiwa"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Kipindi hiki hakijakadiriwa"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Kipindi hiki kimekadiriwa <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Sauti pekee"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Mawimbi dhaifu"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Bonyeza CHAGUA "</b>" ili ufikie menyu ya televisheni."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Hakuna vifaa vya kuingiza maudhui ya runinga vinavyopatikana"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Haiwezi kupata vifaa vya kuingiza maudhui kwenye runinga"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP haiwezi kutumika"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Hakuna maudhui yanayoweza kuonyeshwa pamoja na PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Aina ya kirekebishaji haifai. Fungua programu ya Vituo vya Moja kwa Moja ya vifaa vya kuingiza maudhui ya runinga."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Haikuweza kurekebisha"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Hakuna programu iliyopatikana inayoweza kushughulikia kitendo hiki."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">Rekodi %1$d zimeratibiwa</item>
       <item quantity="one">Rekodi %1$d imeratibiwa</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Ghairi kurekodi"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Acha kurekodi"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Saa"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Cheza kutoka mwanzo"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Endelea kucheza"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Wakati kuna vipindi vingi vya kurekodi kwa wakati mmoja, tutarekodi vipindi vilivyopewa kipaumbele pekee."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Hifadhi"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Rekodi za mara moja hupewa kipaumbele"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Ghairi"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Ghairi"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Sahau"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Komesha"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Angalia ratiba ya kurekodi"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Mpango huu mmoja"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Rekodi hii badala yake"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Ghairi rekodi hii"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Angalia sasa"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Futa rekodi..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Inaweza kurekodiwa"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Kurekodi kumeratibiwa"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Hitilafu ya kurekodi"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Inarekodi"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Imeshindwa kurekodi"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Inasoma maelezo ya programu ili kuunda ratiba"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Inasoma programu"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Inasoma ratiba"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Angalia rekodi za hivi majuzi"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Haikumaliza kurekodi <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Haikumaliza kurekodi <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> na <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Haikumaliza kurekodi <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> na <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Haikumaliza kurekodi <xliff:g id="PROGRAMNAME">%1$s</xliff:g> kwa sababu nafasi ya hifadhi haikutosha."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Haikumaliza kurekodi <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> na <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> kwa sababu nafasi ya hifadhi haikutosha."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Haikumaliza kurekodi <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> na <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> kwa sababu nafasi ya hifadhi haikutosha."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR inahitaji nafasi zaidi ya hifadhi"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Utaweza kurekodi vipindi kwa kutumia DVR. Hata hivyo, kwa sasa hakuna hifadhi ya kutosha kwenye kifaa chako ili kuwezesha DVR kufanya kazi. Tafadhali unganisha hifadhi ya nje isiyopungua GB <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> na ufuate hatua za kuiumbiza kuwa hifadhi ya kifaa."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Utaweza kurekodi vipindi kwa kutumia DVR. Hata hivyo, kwa sasa hakuna hifadhi ya kutosha kwenye kifaa chako ili kuwezesha DVR kufanya kazi. Tafadhali unganisha hifadhi ya nje isiyopungua GB <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> na ufuate hatua za kuiumbiza kuwa hifadhi ya kifaa."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Hifadhi haitoshi"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Kipindi hiki hakitarekodiwa kwa sababu hakuna hifadhi ya kutosha. Jaribu kufuta baadhi ya vipindi vilivyopo."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Hifadhi haipo"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Baadhi ya hifadhi inayotumiwa na DVR haipo. Tafadhali unganisha hifadhi ya nje uliyotumia awali ili uwashe upya DVR yako. Vinginevyo, unaweza kuchagua kusahau hifadhi ikiwa haipatikani tena."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Ungependa kusahau hifadhi?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Hatua hii itaondoa maudhui na ratiba zote ulizohifadhi."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Ungependa kuacha kurekodi?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Itahifadhi maudhui uliyorekodi."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Shughuli ya kurekodi kipindi cha <xliff:g id="PROGRAMNAME">%1$s</xliff:g> itasitishwa kwa sababu inakinzana na kipindi hiki. Maudhui yaliyorekodiwa yatahifadhiwa."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Rekodi zimeratibiwa lakini zinakinzana"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Inaendelea kurekodi japo kuna ukinzani"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> itarekodiwa."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Tayari umeratibu kurekodi kipindi hiki saa <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Tayari kimerekodiwa"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Tayari umerekodi kipindi hiki. Kinapatikana katika maktaba ya DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Shughuli ya kurekodi mfululizo imeratibiwa"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">Imeratibu kurekodi vipindi <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> vya <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one">Imeratibu kurekodi kipindi <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> cha <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">Imeratibu kurekodi vipindi <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> vya <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Haitarekodi vipindi <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> kutokana na ukinzani.</item>
+      <item quantity="one">Imeratibu kurekodi kipindi <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> cha <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Haitarekodi kipindi kutokana na ukinzani.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">Imeratibu kurekodi vipindi <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> vya <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Haitarekodi vipindi <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> vya mfululizo huu na mifululizo mingine kutokana na ukinzani.</item>
+      <item quantity="one">Imeratibu kurekodi kipindi <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> cha <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Haitarekodi vipindi <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> vya mfululizo huu na mifululizo mingine kutokana na ukinzani.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">Imeratibu kurekodi vipindi <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> vya <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Haitarekodi kipindi 1 cha mifululizo mingine kutokana na ukinzani.</item>
+      <item quantity="one">Imeratibu kurekodi kipindi <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> cha <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Haitarekodi kipindi 1 cha mifululizo mingine kutokana na ukinzani.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">Imeratibu kurekodi vipindi <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> vya <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. Haitarekodi vipindi <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> vya mifululizo mingine kutokana na ukinzani.</item>
+      <item quantity="one">Imeratibu kurekodi kipindi <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> cha <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Haitarekodi vipindi <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> vya mifululizo mingine kutokana na ukinzani.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Haikupata programu iliyorekodiwa."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Rekodi zinazohusiana"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Hakuna maelezo ya programu)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">Rekodi %1$d</item>
       <item quantity="one">Rekodi %1$d</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Ungependa kukomesha kurekodi mfululizo?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Vipindi vilivyorekodiwa vitaendelea kupatikana katika maktaba ya DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Komesha"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Hakuna vipindi vinavyopeperushwa kwa sasa."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Hakuna vipindi vinavyopatikana.\nVitarekodiwa pindi vitakapopatikana."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(Dakika %1$d)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Leo <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Kesho <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Alama"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Vipindi Vilivyorekodiwa"</string>
 </resources>
diff --git a/res/values-ta-v23/strings.xml b/res/values-ta-rIN-v23/strings.xml
similarity index 100%
rename from res/values-ta-v23/strings.xml
rename to res/values-ta-rIN-v23/strings.xml
diff --git a/res/values-ta/arrays.xml b/res/values-ta-rIN/arrays.xml
similarity index 100%
rename from res/values-ta/arrays.xml
rename to res/values-ta-rIN/arrays.xml
diff --git a/res/values-ta/rating_system_strings.xml b/res/values-ta-rIN/rating_system_strings.xml
similarity index 100%
rename from res/values-ta/rating_system_strings.xml
rename to res/values-ta-rIN/rating_system_strings.xml
diff --git a/res/values-ta/strings.xml b/res/values-ta-rIN/strings.xml
similarity index 76%
rename from res/values-ta/strings.xml
rename to res/values-ta-rIN/strings.xml
index 7d13e3c..43e1a71 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"மோனோ"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"ஸ்டீரியோ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"இயக்கக் கட்டுப்பாடுகள்"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"சமீபத்திய சேனல்கள்"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"சேனல்கள்"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"டிவி விருப்பங்கள்"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP விருப்பங்கள்"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"இந்தச் சேனலுக்கு இயக்கக் கட்டுப்பாடுகள் இல்லை"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"இயக்கு அல்லது இடைநிறுத்து"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"வேகமாக முன் நகர்த்து"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"விரிவான வசனங்கள்"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"காட்சிப் பயன்முறை"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"இயக்கத்தில்"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"முடக்கத்தில்"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"மல்டி-ஆடியோ"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"மேலும் சேனல்கள்"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"அமைப்புகள்"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"மூலம்"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"மாற்று"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"இயக்கத்தில்"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"முடக்கத்தில்"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ஒலி"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"முதன்மை"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP சாளரம்"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"தளவமைப்பு"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"கீழ் வலதுபுறம்"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"மேல் வலதுபுறம்"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"மேல் இடதுபுறம்"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"கீழ் இடதுபுறம்"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"அருகருகே"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"அளவு"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"பெரியது"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"சிறியது"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"உள்ளீட்டு மூலம்"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"டிவி (ஆண்டெனா/கேபிள்)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"நிகழ்ச்சி தகவல் இல்லை"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"தகவல் இல்லை"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"தடுக்கப்பட்ட சேனல்"</string>
-    <string name="default_language" msgid="4122326459624337928">"தெரியாத மொழி"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"தெரியாத மொழி"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"வசனங்கள் %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"விரிவான வசனங்கள்"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"முடக்கு"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"வடிவமைப்பைத் தனிப்பயனாக்கவும்"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"இதன்படி குழுவாக்கு"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"இந்த நிகழ்ச்சி தடுக்கப்பட்டுள்ளது"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"இந்த நிகழ்ச்சி மதிப்பிடப்படவில்லை"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"இந்த நிகழ்ச்சி <xliff:g id="RATING">%1$s</xliff:g> என மதிப்பிடப்பட்டுள்ளது"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"தன்னியக்க ஸ்கேனை உள்ளீடு ஆதரிக்காது"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"’<xliff:g id="TV_INPUT">%s</xliff:g>’க்கான தன்னியக்க ஸ்கேனைத் தொடங்க முடியவில்லை"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d சேனல் சேர்க்கப்பட்டது</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"சேனல்கள் எதுவும் சேர்க்கப்படவில்லை"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ட்யூனர்"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"பெற்றோர் கட்டுப்பாடுகள்"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"இயக்கு"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"முடக்கு"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"பிற நாடுகள்"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"ஏதுமில்லை"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ஏதுமில்லை"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"மதிப்பிடாதது"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"மதிப்பிடாத நிகழ்ச்சிகளைத் தடு"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"ஏதுமில்லை"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"அதிகக் கட்டுப்பாடுகள்"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"நடுத்தரக் கட்டுப்பாடுகள்"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"இந்தச் சேனலைப் பார்க்க பின்னை உள்ளிடவும்"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"இந்த நிகழ்ச்சியைப் பார்க்க பின்னை உள்ளிடவும்"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"இந்த நிகழ்ச்சி <xliff:g id="RATING">%1$s</xliff:g> என மதிப்பிடப்பட்டுள்ளது. நிகழ்ச்சியைப் பார்க்க, உங்கள் பின்னை உள்ளிடவும்"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"இந்த நிகழ்ச்சி மதிப்பிடப்படவில்லை. இதைப் பார்க்க, உங்கள் பின்னை உள்ளிடவும்"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"பின்னை உள்ளிடவும்"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"பெற்றோர் கட்டுப்பாடுகளை அமைக்க, PINஐ உருவாக்கவும்"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"புதிய PINஐ உள்ளிடவும்"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN தவறானது. மீண்டும் முயலவும்."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"மீண்டும் முயலவும், PIN பொருந்தவில்லை"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"அஞ்சல் குறியீட்டை உள்ளிடவும்."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"நேரலைச் சேனல்கள் பயன்பாடானது, டிவி சேனல்களின் முழுமையான நிகழ்ச்சி வழிகாட்டியை வழங்குவதற்கு அஞ்சல் குறியீட்டைப் பயன்படுத்தும்."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"அஞ்சல் குறியீட்டை உள்ளிடவும்"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"தவறான அஞ்சல் குறியீடு"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"அமைப்புகள்"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"சேனல் பட்டியலைத் தனிப்பயனாக்கு"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"நிகழ்ச்சி வழிகாட்டியில் சேர்ப்பதற்கான சேனல்களைத் தேர்வுசெய்க"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"சேனல் மூலங்கள்"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"புதிய சேனல்கள் உள்ளன"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"பெற்றோர் கட்டுப்பாடுகள்"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"டைம்ஷிஃப்ட்"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"நேரலை நிகழ்ச்சிகளைப் பார்க்கும் போதே ரெக்கார்டு செய்யலாம் என்பதால், அவற்றை இடைநிறுத்தலாம் அல்லது ரீவைண்ட் செய்து பார்க்கலாம்.\nஎச்சரிக்கை: இது சேமிப்பகத்தை அதிகளவு பயன்படுத்தும் என்பதால், சாதனச் சேமிப்பகத்தின் ஆயுளைக் குறைக்கக்கூடும்."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"ஓப்பன் சோர்ஸ் உரிமங்கள்"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"ஓப்பன் சோர்ஸ் உரிமங்கள்"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"கருத்து அனுப்பு"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"பதிப்பு"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"இந்தச் சேனலைப் பார்க்க, வலது பக்கம் அழுத்தி, உங்கள் PINஐ உள்ளிடவும்"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"இந்த நிகழ்ச்சியைப் பார்க்க, வலது பக்கம் அழுத்தி PINஐ உள்ளிடவும்"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"இந்த நிகழ்ச்சி மதிப்பிடப்படவில்லை.\nஇதைப் பார்க்க, \"Right\" என்பதை அழுத்தி, உங்கள் பின்னை உள்ளிடவும்"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"இந்த நிகழ்ச்சி <xliff:g id="RATING">%1$s</xliff:g> என மதிப்பிடப்பட்டுள்ளது.\nஅதைப் பார்க்க, வலது பக்கம் அழுத்தி, பின்னை உள்ளிடவும்."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"இந்தச் சேனலைப் பார்க்க, இயல்புநிலை லைவ் டிவி பயன்பாட்டைப் பயன்படுத்தவும்."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"இந்த நிகழ்ச்சியைப் பார்க்க, இயல்புநிலை லைவ் டிவி பயன்பாட்டைப் பயன்படுத்தவும்."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"இந்த நிகழ்ச்சி மதிப்பிடப்படவில்லை.\nஇதைப் பார்க்க, இயல்பு லைவ் டிவி பயன்பாட்டைப் பயன்படுத்தவும்."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"இந்த நிகழ்ச்சி <xliff:g id="RATING">%1$s</xliff:g> என மதிப்பிடப்பட்டுள்ளது.\nஇந்த நிகழ்ச்சியைப் பார்க்க, இயல்புநிலை லைவ் டிவி பயன்பாட்டைப் பயன்படுத்தவும்."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"நிகழ்ச்சி தடுக்கப்பட்டுள்ளது"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"இந்த நிகழ்ச்சி மதிப்பிடப்படவில்லை"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"இந்த நிகழ்ச்சி <xliff:g id="RATING">%1$s</xliff:g> என மதிப்பிடப்பட்டுள்ளது"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ஆடியோ மட்டும்"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"வலுவற்ற சிக்னல்"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"TV மெனுவை அணுக, "<b>"SELECTஐ அழுத்தவும்"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"டிவி உள்ளீடு இல்லை"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"டிவி உள்ளீடு இல்லை"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP ஆதரிக்கப்படவில்லை"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP உடன் காண்பிக்கத்தக்க உள்ளீடு எதுவுமில்லை"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ட்யூனர் வகை பொருந்தவில்லை. ட்யூனர் வகை டிவி உள்ளீட்டிற்கு நேரலைச் சேனல்கள் பயன்பாட்டைத் துவங்கவும்."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ட்யூன் செய்ய முடியவில்லை"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"இந்தச் செயலைச் செய்வதற்கான பயன்பாடு எதுவுமில்லை."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d ரெக்கார்டிங்குகள் திட்டமிடப்பட்டன</item>
       <item quantity="one">%1$d ரெக்கார்டிங் திட்டமிடப்பட்டது</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"ரெக்கார்டிங்கை ரத்துசெய்"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"ரெக்கார்டிங்கை நிறுத்து"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"இயக்கு"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"முதலிலிருந்து இயக்கு"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"மீண்டும் தொடங்கு"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"ஒரே நேரத்தில் பல நிகழ்ச்சிகளை ரெக்கார்டு செய்ய வேண்டியிருந்தால், அதிக முன்னுரிமைகளைக் கொண்ட நிகழ்ச்சிகள் மட்டுமே ரெக்கார்டு செய்யப்படும்."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"சேமி"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ஒரே முறை ரெக்கார்டு செய்யக்கூடியவற்றுக்கு மிக அதிக முன்னுரிமை வழங்கு"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"ரத்துசெய்"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"ரத்துசெய்"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"நீக்கு"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"நிறுத்து"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"ரெக்கார்டிங் ஷெட்யூலைக் காட்டு"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"இந்த நிகழ்ச்சியை மட்டும்"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"பதிலாக, இதை ரெக்கார்டு செய்"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"இந்த ரெக்கார்டிங்கை ரத்துசெய்"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"இப்போது காட்டு"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ரெக்கார்டிங்குகளை நீக்கு…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"ரெக்கார்டு செய்யக்கூடியது"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ரெக்கார்டிங் திட்டமிடப்பட்டது"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ரெக்கார்டிங்கில் முரண்பாடு"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"ரெக்கார்ட் செய்யப்படுகிறது"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ரெக்கார்டு செய்ய முடியவில்லை"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"ரெக்கார்டிங் ஷெட்யூல்களை உருவாக்க, நிகழ்ச்சிகளைப் படிக்கிறது"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"நிகழ்ச்சிகளைப் படிக்கிறது"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"நிகழ்ச்சிகளைப் படிக்கிறது"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"சமீபத்திய ரெக்கார்டிங்குகளைக் காட்டு"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>ஐ ரெக்கார்டு செய்வது முடிவடையவில்லை."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> மற்றும் <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>ஐ ரெக்கார்டு செய்வது முடிவடையவில்லை."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ஆகியவற்றை ரெக்கார்டு செய்வது முடிவடையவில்லை."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"போதுமான சேமிப்பிடம் இல்லாததால், <xliff:g id="PROGRAMNAME">%1$s</xliff:g>ஐ ரெக்கார்டு செய்வது முடிவடையவில்லை."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"போதுமான சேமிப்பிடம் இல்லாததால், <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> மற்றும் <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>ஐ ரெக்கார்டு செய்வது முடிவடையவில்லை."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"போதுமான சேமிப்பிடம் இல்லாததால், <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>, <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ஆகியவற்றை ரெக்கார்டு செய்வது முடிவடையவில்லை."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVRக்கு அதிகச் சேமிப்பிடம் தேவை"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"நீங்கள் DVR மூலம் நிகழ்ச்சிகளைப் பதிவுசெய்ய முடியும். எனினும், DVR சரியாக வேலை செய்வதற்குத் தேவைப்படும் போதுமான சேமிப்பகம் இப்போது சாதனத்தில் இல்லை. <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>ஜி.பை. அல்லது அதற்கும் அதிகமான அளவில் உள்ள வெளிப்புற இயக்ககத்தை இணைக்கவும். பின் அதைச் சாதனச் சேமிப்பகமாகப் பயன்படுத்த, இந்தப் படிகளைப் பின்பற்றவும்."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"நீங்கள் DVR மூலம் நிகழ்ச்சிகளைப் பதிவுசெய்ய முடியும். எனினும், DVR சரியாக வேலை செய்வதற்குத் தேவைப்படும் போதுமான சேமிப்பகம் இப்போது சாதனத்தில் இல்லை. <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>ஜி.பை. அல்லது அதற்கும் அதிகமான அளவில் உள்ள வெளிப்புற இயக்ககத்தை இணைக்கவும். பின் அதைச் சாதனச் சேமிப்பகமாகப் பயன்படுத்த, இந்தப் படிகளைப் பின்பற்றவும்."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"போதுமான சேமிப்பிடம் இல்லை"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"போதுமான சேமிப்பிடம் இல்லாததால், இந்த நிகழ்ச்சி ரெக்கார்டு செய்யப்படாது. ஏற்கனவே உள்ள சில ரெக்கார்டிங்குகளை நீக்கவும்."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"சேமிப்பகம் இல்லை"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR பயன்படுத்தும் சேமிப்பகம் இல்லை. DVRஐ மீண்டும் இயக்கும் முன், நீங்கள் பயன்படுத்தும் வெளிப்புற டிரைவை இணைக்கவும். மாற்றுவழியாக, சேமிப்பகத்தை இனி பயன்படுத்த மாட்டீர்கள் எனில், அதை நீக்கும்படியும் தேர்ந்தெடுக்கலாம்."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"சேமிப்பகத்தை நீக்கவா?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"பதிவுசெய்த உள்ளடக்கத்தையும் திட்ட அட்டவணைகளையும் இழப்பீர்கள்."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"ரெக்கார்டு செய்வதை நிறுத்தவா?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"ரெக்கார்டு செய்த உள்ளடக்கம் சேமிக்கப்படும்."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>ஐ ரெக்கார்டு செய்வது இந்த நிகழ்ச்சியுடன் முரண்படுவதால், ரெக்கார்டிங் நிறுத்தப்படும். ரெக்கார்டு செய்த உள்ளடக்கம் சேமிக்கப்படும்."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ரெக்கார்டிங் திட்டமிடப்பட்டது, ஆனால் முரண்பாடுகள் உள்ளன"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ரெக்கார்டு செய்வது தொடங்கப்பட்டது, ஆனால் முரண்பாடுகள் உள்ளன"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ரெக்கார்டு செய்யப்படும்."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>க்கு ரெக்கார்டு செய்வதற்காக இந்த நிகழ்ச்சி ஏற்கனவே திட்டமிடப்பட்டுள்ளது."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"ஏற்கனவே ரெக்கார்டு செய்யப்பட்டது"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"இந்த நிகழ்ச்சி ஏற்கனவே ரெக்கார்டு செய்யப்பட்டது. மேலும் DVR நூலகத்தில் கிடைக்கும்."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"தொடர் ரெக்கார்டிங் திட்டமிடப்பட்டது"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ரெக்கார்டிங்குகள் திட்டமிடப்பட்டுள்ளன.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ரெக்கார்டிங் திட்டமிடப்பட்டுள்ளது.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ரெக்கார்டிங்குகள் திட்டமிடப்பட்டுள்ளன. முரண்பாடுகளின் காரணமாக, இந்தத் தொடரின் <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> எபிசோடுகள் ரெக்கார்டு செய்யப்படாது.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ரெக்கார்டிங் திட்டமிடப்பட்டுள்ளது. முரண்பாடுகளின் காரணமாக, இது ரெக்கார்டு செய்யப்படாது.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ரெக்கார்டிங்குகள் திட்டமிடப்பட்டுள்ளன. முரண்பாடுகளின் காரணமாக, இந்தத் தொடர் மற்றும் பிற தொடரின் <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> எபிசோடுகள் ரெக்கார்டு செய்யப்படாது.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ரெக்கார்டிங் திட்டமிடப்பட்டுள்ளது. முரண்பாடுகளின் காரணமாக, இந்தத் தொடர் மற்றும் பிற தொடரின் <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> எபிசோடுகள் ரெக்கார்டு செய்யப்படாது.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ரெக்கார்டிங்குகள் திட்டமிடப்பட்டுள்ளன. முரண்பாடுகளின் காரணமாக, பிற தொடரின் ஒரு எபிசோடு ரெக்கார்டு செய்யப்படாது.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ரெக்கார்டிங் திட்டமிடப்பட்டுள்ளது. முரண்பாடுகளின் காரணமாக, பிற தொடரின் ஒரு எபிசோடு ரெக்கார்டு செய்யப்படாது.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ரெக்கார்டிங்குகள் திட்டமிடப்பட்டுள்ளன. முரண்பாடுகளின் காரணமாக, பிற தொடரின் <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> எபிசோடுகள் ரெக்கார்டு செய்யப்படாது.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> தொடருக்கு <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ரெக்கார்டிங் திட்டமிடப்பட்டுள்ளது. முரண்பாடுகளின் காரணமாக, பிற தொடரின் <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> எபிசோடுகள் ரெக்கார்டு செய்யப்படாது.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"ரெக்கார்டு செய்த நிகழ்ச்சி இல்லை."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"தொடர்புடைய ரெக்கார்டிங்குகள்"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(நிகழ்ச்சி விளக்கம் இல்லை)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d ரெக்கார்டிங்குகள்</item>
       <item quantity="one">%1$d ரெக்கார்டிங்</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"தொடர் ரெக்கார்டிங்கை நிறுத்தவா?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"ரெக்கார்டு செய்யப்பட எபிசோடுகள் தொடர்ந்து DVR நூலகத்தில் இருக்கும்."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"நிறுத்து"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"இப்போது எந்த எபிசோடுகளும் நேரலையில் இல்லை."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"எபிசோடுகள் இல்லை.\nஅவை கிடைக்கும் போது ரெக்கார்டு செய்யப்படும்."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d நிமிடங்கள்)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"இன்று <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"நாளை <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"ஸ்கோர்"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"ரெக்கார்டு செய்த நிகழ்ச்சிகள்"</string>
 </resources>
diff --git a/res/values-te-v23/strings.xml b/res/values-te-rIN-v23/strings.xml
similarity index 100%
rename from res/values-te-v23/strings.xml
rename to res/values-te-rIN-v23/strings.xml
diff --git a/res/values-te/arrays.xml b/res/values-te-rIN/arrays.xml
similarity index 100%
rename from res/values-te/arrays.xml
rename to res/values-te-rIN/arrays.xml
diff --git a/res/values-te/rating_system_strings.xml b/res/values-te-rIN/rating_system_strings.xml
similarity index 100%
rename from res/values-te/rating_system_strings.xml
rename to res/values-te-rIN/rating_system_strings.xml
diff --git a/res/values-te/strings.xml b/res/values-te-rIN/strings.xml
similarity index 77%
rename from res/values-te/strings.xml
rename to res/values-te-rIN/strings.xml
index 274be2c..f6b8e53 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"మోనో"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"స్టీరియో"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"ప్లే నియంత్రణలు"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"ఇటీవలి ఛానెళ్లు"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ఛానెల్‌లు"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"టీవీ ఎంపికలు"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP ఎంపికలు"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ఈ ఛానెల్ యొక్క ప్లే నియంత్రణలు అందుబాటులో లేవు"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"ప్లే చేస్తుంది లేదా పాజ్ చేస్తుంది"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"ఫాస్ట్ ఫార్వార్డ్ చేస్తుంది"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"సంవృత శీర్షికలు"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"ప్రదర్శన మోడ్"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"ఆన్‌లో ఉంది"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"ఆఫ్‌లో ఉంది"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"బహుళ-ఆడియో"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"మరిన్ని ఛానెల్‌లను పొందండి"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"సెట్టింగ్‌లు"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"మూలం"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"మార్చు"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"ఆన్‌లో ఉంది"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"ఆఫ్‌లో ఉంది"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"ధ్వని"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"ప్రధానమైనది"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP విండో"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"లేఅవుట్"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"దిగువ కుడివైపు"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ఎగువ కుడివైపు"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ఎగువ ఎడమవైపు"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"దిగువ ఎడమవైపు"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"పక్కపక్కన"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"పరిమాణం"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"పెద్దది"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"చిన్నది"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"ఇన్‌పుట్ మూలం"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"టీవీ (యాంటెన్నా/కేబుల్)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"కార్యక్రమ సమాచారం లేదు"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"సమాచారం లేదు"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"బ్లాక్ చేసిన ఛానెల్"</string>
-    <string name="default_language" msgid="4122326459624337928">"భాష తెలియదు"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"భాష తెలియదు"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"ఉపశీర్షికలు %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"సంవృత శీర్షికలు"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"ఆఫ్ చేయి"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"ఆకృతీకరణను అనుకూలీకరించు"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"ఈ ప్రకారం సమూహం చేయి"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"ఈ కార్యక్రమం బ్లాక్ చేయబడింది"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"ఈ కార్యక్రమం రేట్ చేయబడలేదు"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"ఈ కార్యక్రమం <xliff:g id="RATING">%1$s</xliff:g> అని రేట్ చేయబడింది"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"స్వయంచాలకంగా స్కాన్ చేయడానికి ఇన్‌పుట్ మద్దతు ఇవ్వలేదు"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' కోసం ఆటో-స్కాన్‌ని ప్రారంభించడం సాధ్యపడలేదు"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d ఛానెల్ జోడించబడింది</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"ఛానెల్‌లు జోడించబడలేదు"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ట్యూనర్"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"తల్లిదండ్రుల నియంత్రణలు"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"ఆన్ చేయి"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"ఆఫ్ చేయి"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"ఇతర దేశాలు"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"ఏదీ లేదు"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ఏదీ లేదు"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"రేట్ చేయనిది"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"రేట్ చేయని కార్యక్రమాలను బ్లాక్ చేయండి"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"ఏదీ లేదు"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"అధిక పరిమితులు"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"మధ్యస్థ పరిమితులు"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"ఈ ఛానెల్‌ని చూడటానికి మీ పిన్‌ని నమోదు చేయండి"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"ఈ కార్యక్రమాన్ని చూడటానికి మీ పిన్‌ని నమోదు చేయండి"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"ఈ కార్యక్రమానికి <xliff:g id="RATING">%1$s</xliff:g> అని రేట్ చేయబడింది. ఈ కార్యక్రమాన్ని చూడటానికి మీ PINని నమోదు చేయండి"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"ఈ కార్యక్రమం రేట్ చేయబడలేదు. ఈ కార్యక్రమాన్ని చూడటానికి మీ PINని నమోదు చేయండి"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"మీ పిన్‌ని నమోదు చేయండి"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"తల్లిదండ్రుల నియంత్రణలను సెట్ చేయడానికి, పిన్‌ని సృష్టించండి"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"కొత్త పిన్‌ని నమోదు చేయండి"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"ఆ పిన్ తప్పు. మళ్లీ ప్రయత్నించండి."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"మళ్లీ ప్రయత్నించండి, పిన్ సరిపోలలేదు"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"మీ జిప్ కోడ్‌ను నమోదు చేయండి."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"ప్రత్యక్ష ప్రసార ఛానెల్‌ల అనువర్తనం టీవీ ఛానెల్‌లకి సంబంధించిన పూర్తి ప్రోగ్రామ్ గైడ్‌ను అందించడానికి జిప్ కోడ్‌ను ఉపయోగిస్తుంది."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"మీ జిప్ కోడ్‌ను నమోదు చేయండి"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"జిప్ కోడ్ చెల్లదు"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"సెట్టింగ్‌లు"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"ఛానెల్‌ జాబితా అనుకూలీకరించండి"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"మీ ప్రోగ్రామ్ గైడ్ కోసం ఛానెల్‌లను ఎంచుకోండి"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"ఛానెల్ సోర్స్‌లు"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"కొత్త ఛానెల్‌లు అందుబాటులో ఉన్నాయి"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"తల్లిదండ్రుల నియంత్రణలు"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"టైమ్‌షిఫ్ట్"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"ప్రత్యక్ష ప్రసార కార్యక్రమాలను చూస్తున్నప్పుడు రికార్డ్ కూడా చేయండి, ఇలా చేయడం ద్వారా మీరు కోరుకున్నప్పుడు వాటిని పాజ్ లేదా రివైండ్ చేయవచ్చు.\nహెచ్చరిక: ఇది నిల్వను అధికంగా ఉపయోగించడం ద్వారా అంతర్గత నిల్వ జీవితకాలాన్ని తగ్గించవచ్చు."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"ఓపెన్ సోర్స్ లైసెన్స్‌లు"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"ఓపెన్ సోర్స్ లైసెన్స్‌లు"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"అభిప్రాయాన్ని పంపు"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"సంస్కరణ"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"ఈ ఛానెల్‌ను చూడటానికి, కుడివైపు బటన్ నొక్కి, మీ పిన్‌ని నమోదు చేయండి"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"ఈ ప్రోగ్రామ్‌ని చూడటానికి, కుడివైపు బటన్ నొక్కి, మీ పిన్‌ని నమోదు చేయండి"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"ఈ కార్యక్రమం రేట్ చేయబడలేదు.\nఈ కార్యక్రమాన్ని చూడటానికి, కుడి వైపున నొక్కి, మీ PINని నమోదు చేయండి"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"ఈ కార్యక్రమం <xliff:g id="RATING">%1$s</xliff:g> అని రేట్ చేయబడింది.\nఈ కార్యక్రమాన్ని చూడటానికి, కుడివైపు బటన్ నొక్కి, మీ PINని నమోదు చేయండి."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"ఈ ఛానెల్‌ను చూడటానికి, డిఫాల్ట్ లైవ్ టీవీ అనువర్తనాన్ని ఉపయోగించండి."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"ఈ కార్యక్రమాన్ని చూడటానికి, డిఫాల్ట్ లైవ్ టీవీ అనువర్తనాన్ని ఉపయోగించండి."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"ఈ కార్యక్రమం రేట్ చేయబడలేదు.\nఈ కార్యక్రమాన్ని చూడటానికి, డిఫాల్ట్ ప్రత్యక్ష TV అప్లికేషన్‌ను ఉపయోగించండి."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"ఈ కార్యక్రమానికి <xliff:g id="RATING">%1$s</xliff:g> అని రేట్ చేయబడింది.\nఈ కార్యక్రమాన్ని చూడటానికి, డిఫాల్ట్ లైవ్ టీవీ అనువర్తనాన్ని ఉపయోగించండి."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"కార్యక్రమం బ్లాక్ చేయబడింది"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"ఈ కార్యక్రమం రేట్ చేయబడలేదు"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"ఈ కార్యక్రమం <xliff:g id="RATING">%1$s</xliff:g> అని రేట్ చేయబడింది"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"ఆడియో మాత్రమే"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"సిగ్నల్ బలహీనంగా ఉంది"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"టీవీ మెనుని ప్రాప్యత చేయడానికి "<b>"ఎంచుకోండి నొక్కండి"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"టీవీ ఇన్‌పుట్ కనుగొనబడలేదు"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"టీవీ ఇన్‌పుట్‌ను కనుగొనడం సాధ్యపడదు"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIPకి మద్దతు లేదు"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIPతో చూపబడే ఇన్‌పుట్ ఏదీ అందుబాటులో లేదు"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ట్యూనర్ రకం తగినది కాదు. దయచేసి ట్యూనర్ రకం టీవీ ఇన్‌పుట్ కోసం లైవ్ ఛానెల్‌లు అనువర్తనాన్ని ప్రారంభించండి."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ట్యూన్ విఫలమైంది"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ఈ చర్యను నిర్వహించడానికి అనువర్తనం ఏదీ కనుగొనబడలేదు."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d రికార్డింగ్‌లు చేయాలి</item>
       <item quantity="one">%1$d రికార్డింగ్ చేయాలి</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"రికార్డింగ్‌ను రద్దు చేయి"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"రికార్డింగ్‌ను ఆపివేయి"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"చూడండి"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"మొదటి నుండి ప్లే చేయి"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"ప్లే చేయడం కొనసాగించు"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"ఒకే సమయంలో చాలా ఎక్కువ కార్యక్రమాలు రికార్డ్ చేయాల్సినప్పుడు, అధిక ప్రాధాన్యతలు గలవి మాత్రమే రికార్డ్ చేయబడతాయి."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"సేవ్ చేయి"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"ఒక పర్యాయ రికార్డింగ్‌లు అత్యధిక ప్రాధాన్యతను కలిగి ఉంటాయి"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"రద్దు చేయి"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"రద్దు చేయి"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"విస్మరించు"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"ఆపివేయి"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"రికార్డింగ్ షెడ్యూల్ చూడండి"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"ఈ ఒక్క కార్యక్రమం"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"బదులుగా దీన్ని రికార్డ్ చేయి"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ఈ రికార్డింగ్‌ను రద్దు చేయి"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"ఇప్పుడే చూడండి"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"రికార్డింగ్‌లను తొలగించు…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"రికార్డ్ చేయవచ్చు"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"రికార్డింగ్ షెడ్యూల్ చేయబడింది"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"రికార్డింగ్ వైరుధ్యం"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"రికార్డ్ అవుతోంది"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"రికార్డింగ్ విఫలమైంది"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"రికార్డింగ్ షెడ్యూళ్లను రూపొందించడానికి కార్యక్రమాలను చదువుతోంది"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"కార్యక్రమాలను చదువుతోంది"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"కార్యక్రమాలను చదువుతోంది"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"ఇటీవలి రికార్డింగ్‌లను వీక్షించండి"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> రికార్డింగ్ అసంపూర్ణంగా ఉంది."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> మరియు <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> రికార్డింగ్‌లు అసంపూర్ణంగా ఉన్నాయి."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> మరియు <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> రికార్డింగ్‌లు అసంపూర్ణంగా ఉన్నాయి."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"తగినంత నిల్వ లేని కారణంగా, <xliff:g id="PROGRAMNAME">%1$s</xliff:g> రికార్డింగ్ పూర్తి కాలేదు."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"తగినంత నిల్వ లేని కారణంగా, <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> మరియు <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> రికార్డింగ్‌లు పూర్తి కాలేదు."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"తగినంత నిల్వ లేని కారణంగా, <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> మరియు <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> రికార్డింగ్‌లు పూర్తి కాలేదు."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVRకు మరింత నిల్వ అవసరం"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"మీరు DVRతో కార్యక్రమాలను రికార్డ్ చేయగలుగుతారు. అయితే, ప్రస్తుతం DVR పని చేయడానికి మీ పరికరంలో తగినంత నిల్వ ఖాళీ లేదు. దయచేసి <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB లేదా అంతకంటే ఎక్కువ ఖాళీ స్థలం గల బయటి డ్రైవ్‌ను కనెక్ట్ చేసి, ఆపై దాన్ని పరికర నిల్వగా ఫార్మాట్ చేయడానికి సూచనలను అనుసరించండి."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"మీరు DVRతో కార్యక్రమాలను రికార్డ్ చేయగలుగుతారు. అయితే, ప్రస్తుతం DVR పని చేయడానికి మీ పరికరంలో తగినంత నిల్వ ఖాళీ లేదు. దయచేసి <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB లేదా అంతకంటే ఎక్కువ ఖాళీ స్థలం గల బయటి డ్రైవ్‌ను కనెక్ట్ చేసి, ఆపై దాన్ని పరికర నిల్వగా ఫార్మాట్ చేయడానికి సూచనలను అనుసరించండి."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"తగినంత నిల్వ లేదు"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"తగినంత నిల్వ లేనందున ఈ కార్యక్రమం రికార్డ్ చేయబడదు. ఇప్పటికే ఉన్న కొన్ని రికార్డింగ్‌లను తొలగించడానికి ప్రయత్నించండి."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"నిల్వ కనిపించడం లేదు"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR ద్వారా ఉపయోగించబడిన కొంత నిల్వ కనిపించడం లేదు. దయచేసి DVRని పునఃప్రారంభించడానికి మీరు ఇంతకుముందు ఉపయోగించిన బయటి డిస్క్‌ను కనెక్ట్ చేయండి. లేదంటే, అది అందుబాటులో లేని పక్షంలో మీరు ఆ నిల్వను విస్మరించమని ఎంచుకోవచ్చు."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"నిల్వను విస్మరించాలా?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"మీ మొత్తం రికార్డ్ చేసిన కంటెంట్‌ను మరియు షెడ్యూల్‌లను కోల్పోతారు."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"రికార్డింగ్ ఆపివేయాలా?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"రికార్డ్ అయిన కంటెంట్ సేవ్ చేయబడుతుంది."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> యొక్క రికార్డింగ్‌కి ఈ కార్యక్రమంతో వైరుధ్యం తలెత్తినందున అది ఆపివేయబడుతుంది. రికార్డ్ చేసిన కంటెంట్ సేవ్ చేయబడుతుంది."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"రికార్డింగ్ షెడ్యూల్ చేయబడింది కానీ మిగిలిన వాటితో వైరుధ్యాలను కలిగి ఉంది"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"రికార్డింగ్ ప్రారంభమైంది, కానీ వైరుధ్యాలను కలిగి ఉంది"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> రికార్డ్ చేయబడుతుంది."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"ఇదే కార్యక్రమం ఇప్పటికే <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>కి రికార్డ్ చేయడానికి షెడ్యూల్ చేయబడింది."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"ఇప్పటికే రికార్డ్ అయింది"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"ఈ ప్రోగ్రామ్ ఇప్పటికే రికార్డ్ అయింది. ఇది DVR లైబ్రరీలో అందుబాటులో ఉంది."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"సిరీస్ రికార్డింగ్ షెడ్యూల్ చేయబడింది"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> రికార్డింగ్‌లు షెడ్యూల్ చేయబడ్డాయి.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> రికార్డింగ్ షెడ్యూల్ చేయబడింది.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> రికార్డింగ్‌లు షెడ్యూల్ చేయబడ్డాయి. వైరుధ్యాల కారణంగా వాటిలో <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> రికార్డ్ చేయబడవు.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> రికార్డింగ్ షెడ్యూల్ చేయబడింది. వైరుధ్యాల కారణంగా ఇది రికార్డ్ చేయబడదు.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> రికార్డింగ్‌లు షెడ్యూల్ చేయబడ్డాయి. వైరుధ్యాల కారణంగా ఈ సిరీస్ మరియు మరో సిరీస్‌లోని <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ఎపిసోడ్‌లు రికార్డ్ చేయబడవు.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> రికార్డింగ్ షెడ్యూల్ చేయబడింది. వైరుధ్యాల కారణంగా ఈ సిరీస్ మరియు మరో సిరీస్‌లోని <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ఎపిసోడ్‌లు రికార్డ్ చేయబడవు.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> రికార్డింగ్‌లు షెడ్యూల్ చేయబడ్డాయి. వైరుధ్యాల కారణంగా మరో సిరీస్‌లోని 1 ఎపిసోడ్ రికార్డ్ చేయబడదు.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> రికార్డింగ్ షెడ్యూల్ చేయబడింది. వైరుధ్యాల కారణంగా మరో సిరీస్‌లోని 1 ఎపిసోడ్ రికార్డ్ చేయబడదు.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> రికార్డింగ్‌లు షెడ్యూల్ చేయబడ్డాయి. వైరుధ్యాల కారణంగా మరో సిరీస్‌లోని <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ఎపిసోడ్‌లు రికార్డ్ చేయబడవు.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g>కి <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> రికార్డింగ్ షెడ్యూల్ చేయబడింది. వైరుధ్యాల కారణంగా మరో సిరీస్‌లోని <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ఎపిసోడ్‌లు రికార్డ్ చేయబడవు.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"రికార్డ్ చేసిన కార్యక్రమం కనుగొనబడలేదు."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"సంబంధిత రికార్డింగ్‌లు"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(కార్యక్రమం వివరణ లేదు)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d రికార్డింగ్‌లు</item>
       <item quantity="one">%1$d రికార్డింగ్</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"సిరీస్ రికార్డింగ్‌ను ఆపివేయాలా?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"రికార్డ్ అయిన ఎపిసోడ్‌లు DVR లైబ్రరీలో అలాగే అందుబాటులో ఉంటాయి."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"ఆపివేయి"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ప్రస్తుతం ఎపిసోడ్‌లు ఏవీ ప్రసారంలో లేవు."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"ఎపిసోడ్‌లు ఏవీ అందుబాటులో లేవు.\nఇవి అందుబాటులోకి వచ్చిన వెంటనే రికార్డ్ చేయబడతాయి."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d నిమిషాలు)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ఈ రోజు"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> రేపు"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"స్కోర్"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"రికార్డ్ చేసిన కార్యక్రమాలు"</string>
 </resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 8424e9b..09bf9bd 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"โมโน"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"สเตอริโอ"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"การควบคุมการเล่น"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"ช่องล่าสุด"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"ช่อง"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"ตัวเลือกทีวี"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"ตัวเลือกของ PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"ไม่มีการควบคุมการเล่นสำหรับช่องนี้"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"เล่นหรือหยุดชั่วคราว"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"กรอไปข้างหน้า"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"คำบรรยาย"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"โหมดการแสดงผล"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"เปิด"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"ปิด"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"หลายเสียง"</string>
-    <string name="options_item_more_channels" msgid="971040969622943300">"รับชมช่องต่างๆ มากขึ้น"</string>
+    <string name="options_item_more_channels" msgid="971040969622943300">"ดูช่องอื่นๆ"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"การตั้งค่า"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"แหล่งที่มา"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"สลับ"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"เปิด"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"ปิด"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"เสียง"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"หลัก"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"หน้าต่าง PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"การจัดวาง"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"ขวาล่าง"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"ขวาบน"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"ซ้ายบน"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"ซ้ายล่าง"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"แสดงคู่กัน"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"ขนาด"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"ใหญ่"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"เล็ก"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"แหล่งที่มาอินพุต"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (สายอากาศ/เคเบิล)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"ไม่มีข้อมูลโปรแกรม"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"ไม่มีข้อมูล"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"ช่องที่ถูกบล็อก"</string>
-    <string name="default_language" msgid="4122326459624337928">"ภาษาที่ไม่รู้จัก"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"ภาษาที่ไม่รู้จัก"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"คำอธิบายภาพ %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"คำบรรยาย"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"ปิด"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"กำหนดค่าการจัดรูปแบบ"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"จัดกลุ่มตาม"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"โปรแกรมนี้ถูกบล็อก"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"รายการนี้ไม่ได้รับการจัดประเภท"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"โปรแกรมนี้เรต <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"อินพุตไม่สนับสนุนการสแกนอัตโนมัติ"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"ไม่สามารถเริ่มการสแกนอัตโนมัติสำหรับ \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -92,7 +74,6 @@
       <item quantity="one">เพิ่มแล้ว %1$d ช่อง</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"ไม่ได้เพิ่มช่อง"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ตัวรับสัญญาณ"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"ควบคุมโดยผู้ปกครอง"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"เปิด"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"ปิด"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"ประเทศอื่นๆ"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"ไม่มี"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"ไม่มี"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"ไม่ได้จัดประเภท"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"บล็อกเกมที่ไม่ได้จัดประเภท"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"ไม่มี"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"ข้อจำกัดสูง"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"ข้อจำกัดปานกลาง"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"ป้อน PIN ของคุณเพื่อดูช่องนี้"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"ป้อน PIN ของคุณเพื่อดูโปรแกรมนี้"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"รายการนี้จัดอยู่ในประเภท <xliff:g id="RATING">%1$s</xliff:g> ป้อน PIN เพื่อดูรายการนี้"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"รายการนี้ไม่ได้รับการจัดประเภท ป้อน PIN เพื่อดูรายการนี้"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"ป้อน PIN ของคุณ"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"หากต้องการตั้งค่าการควบคุมโดยผู้ปกครอง โปรดสร้าง PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"ป้อน PIN ใหม่"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN ไม่ถูกต้อง ลองอีกครั้ง"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"ลองอีกครั้ง PIN ไม่ตรงกัน"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"ป้อนรหัสไปรษณีย์ของคุณ"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"แอป Live TV จะใช้รหัสไปรษณีย์สำหรับการจัดส่งคู่มือรายการทีวีช่องต่างๆ ฉบับเต็ม"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"ป้อนรหัสไปรษณีย์ของคุณ"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"รหัสไปรษณีย์ไม่ถูกต้อง"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"การตั้งค่า"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"กำหนดค่ารายการช่อง"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"เลือกช่องสำหรับคู่มือรายการทีวีของคุณ"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"แหล่งที่มาของช่อง"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"มีช่องใหม่ให้บริการ"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"การควบคุมโดยผู้ปกครอง"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"ไทม์ชิฟท์"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"บันทึกขณะดูเพื่อให้สามารถหยุดชั่วคราวหรือกรอกลับรายการสดได้\nคำเตือน: การดำเนินการนี้อาจลดอายุการใช้งานของพื้นที่เก็บข้อมูลภายในเนื่องจากการใช้งานหนัก"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"ใบอนุญาตโอเพนซอร์ส"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"ใบอนุญาตโอเพนซอร์ส"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"ส่งความคิดเห็น"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"เวอร์ชัน"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"หากต้องการดูช่องนี้ ให้กดขวาและป้อน PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"หากต้องการดูโปรแกรมนี้ ให้กดขวาและป้อน PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"รายการนี้ไม่ได้รับการจัดประเภท\nหากต้องการดูรายการนี้ ให้กด \"สิทธิ์\" และป้อน PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"โปรแกรมนี้เรต <xliff:g id="RATING">%1$s</xliff:g>\nในการดูโปรแกรมนี้ โปรดกดขวาและป้อน PIN"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"หากต้องการดูช่องนี้ ให้ใช้แอปทีวีออนไลน์ที่เป็นค่าเริ่มต้น"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"หากต้องการดูโปรแกรมนี้ ให้ใช้แอปทีวีออนไลน์ที่เป็นค่าเริ่มต้น"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"รายการนี้ไม่ได้รับการจัดประเภท\nหากต้องการดูรายการนี้ ให้ใช้แอป Live TV เริ่มต้น"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"โปรแกรมนี้ได้รับคะแนน <xliff:g id="RATING">%1$s</xliff:g>\nหากต้องการดูโปรแกรมนี้ ให้ใช้แอปทีวีออนไลน์ที่เป็นค่าเริ่มต้น"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"ระบบบล็อกโปรแกรมไว้"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"รายการนี้ไม่ได้รับการจัดประเภท"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"โปรแกรมนี้เรต <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"เฉพาะเสียง"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"สัญญาณไม่ดี"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"กด \"เลือก\""</b>" เพื่อเข้าถึงเมนู TV"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"ไม่พบอินพุต TV"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"ไม่พบอินพุต TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"ไม่สนับสนุน PIP"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"ไม่มีอินพุตที่พร้อมใช้งานซึ่งสามารถแสดงด้วย PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"ประเภทตัวรับสัญญาณไม่เหมาะสม โปรดเปิดแอป Live TV สำหรับอินพุต TV ที่เป็นประเภทตัวรับสัญญาณ"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"การรับสัญญาณล้มเหลว"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"ไม่พบแอปสำหรับการทำงานนี้"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">กำหนดเวลาบันทึกแล้ว %1$d รายการ</item>
       <item quantity="one">กำหนดเวลาบันทึกแล้ว %1$d รายการ</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"ยกเลิกการบันทึก"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"หยุดบันทึก"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"ดู"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"เล่นจากจุดเริ่มต้น"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"เล่นต่อจากที่ค้างไว้"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"เมื่อต้องบันทึกรายการหลายรายการพร้อมกันมากเกินไป ระบบจะบันทึกเฉพาะรายการที่มีลำดับความสำคัญสูงกว่าเท่านั้น"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"บันทึก"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"การบันทึกครั้งเดียวมีความสำคัญสูงสุด"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"ยกเลิก"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"ยกเลิก"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"ไม่จำ"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"หยุด"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"ดูกำหนดการบันทึก"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"โปรแกรมนี้เท่านั้น"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"บันทึกรายการนี้แทน"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"ยกเลิกการบันทึกนี้"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"ดูตอนนี้"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ลบรายการที่บันทึกไว้…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"สามารถบันทึกได้"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"กำหนดเวลาบันทึกแล้ว"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ตารางบันทึกชนกัน"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"กำลังบันทึก"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"การบันทึกล้มเหลว"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"กำลังอ่านรายการเพื่อสร้างกำหนดเวลาการบันทึก"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"กำลังอ่านรายการ"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"กำลังอ่านรายการ"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"ดูการบันทึกล่าสุด"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"การบันทึก <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ไม่สมบูรณ์"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"การบันทึก <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> และ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ไม่สมบูรณ์"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"การบันทึก <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> และ <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ไม่สมบูรณ์"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"การบันทึก <xliff:g id="PROGRAMNAME">%1$s</xliff:g> ไม่สมบูรณ์ เนื่องจากพื้นที่เก็บข้อมูลไม่เพียงพอ"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"การบันทึก <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> และ <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ไม่สมบูรณ์ เนื่องจากพื้นที่เก็บข้อมูลไม่เพียงพอ"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"การบันทึก <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> และ <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> ไม่สมบูรณ์ เนื่องจากพื้นที่เก็บข้อมูลไม่เพียงพอ"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR ต้องการพื้นที่เก็บข้อมูลเพิ่มเติม"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"คุณจะสามารถบันทึกรายการด้วย DVR ได้ อย่างไรก็ตาม ตอนนี้อุปกรณ์ของคุณมีพื้นที่เก็บข้อมูลไม่เพียงพอสำหรับให้ DVR ทำงาน โปรดเชื่อมต่อไดรฟ์ภายนอกที่มีขนาด <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB ขึ้นไป และทำตามขั้นตอนเพื่อฟอร์แมตไดรฟ์ให้เป็นพื้นที่เก็บข้อมูลของอุปกรณ์"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"คุณจะสามารถบันทึกรายการด้วย DVR ได้ อย่างไรก็ตาม ตอนนี้อุปกรณ์ของคุณมีพื้นที่เก็บข้อมูลไม่เพียงพอสำหรับให้ DVR ทำงาน โปรดเชื่อมต่อไดรฟ์ภายนอกที่มีขนาด <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB ขึ้นไป และทำตามขั้นตอนเพื่อฟอร์แมตไดรฟ์ให้เป็นพื้นที่เก็บข้อมูลของอุปกรณ์"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"พื้นที่เก็บข้อมูลไม่เพียงพอ"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"ไม่สามารถบันทึกรายการนี้ได้เนื่องจากพื้นที่เก็บข้อมูลไม่เพียงพอ โปรดลองลบบางรายการที่บันทึกไว้"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"พื้นที่เก็บข้อมูลหายไป"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"พื้นที่เก็บข้อมูลบางส่วนที่ DVR ใช้หายไป โปรดเชื่อมต่อไดรฟ์ภายนอกที่คุณใช้ก่อนเปิดใช้ DVR อีกครั้ง หรือคุณอาจเลือกไม่จำพื้นที่เก็บข้อมูลหากพื้นที่เก็บข้อมูลไม่พร้อมใช้งานอีกต่อไป"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"ไม่จำพื้นที่เก็บข้อมูลใช่ไหม"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"เนื้อหาและกำหนดการทั้งหมดที่คุณบันทึกไว้จะหายไป"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"หยุดบันทึกใช่ไหม"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"ระบบจะเก็บเนื้อหาที่บันทึกไว้"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"การบันทึก <xliff:g id="PROGRAMNAME">%1$s</xliff:g> จะหยุดลงเนื่องจากตารางบันทึกชนกับรายการนี้ เนื้อหาที่บันทึกแล้วจะได้รับการเก็บไว้"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"กำหนดการบันทึกรายการชนกัน"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"เริ่มบันทึกรายการแล้ว แต่กำหนดการชนกัน"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"ระบบจะบันทึก <xliff:g id="PROGRAMNAME">%1$s</xliff:g>"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"มีกำหนดบันทึกรายการเดียวกันนี้แล้วเวลา <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"บันทึกไว้แล้ว"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"บันทึกรายการนี้ไว้แล้ว สามารถดูได้ที่ห้องสมุด DVR"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"กำหนดเวลาบันทึกซีรีส์แล้ว"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_3">%2$s</xliff:g></item>
+      <item quantity="one">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_1">%2$s</xliff:g></item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> รายการจะไม่มีการบันทึกเนื่องจากตารางบันทึกชนกัน</item>
+      <item quantity="one">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> จะไม่มีการบันทึกเนื่องจากเนื่องจากตารางบันทึกชนกัน</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ซีรีส์นี้และซีรีส์อื่น <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ตอนจะไม่มีการบันทึกเนื่องจากตารางบันทึกชนกัน</item>
+      <item quantity="one">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ซีรีส์นี้และซีรีส์อื่น <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ตอนจะไม่มีการบันทึกเนื่องจากตารางบันทึกชนกัน</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_3">%2$s</xliff:g> ซีรีส์อื่น 1 ตอนจะไม่มีการบันทึกเนื่องจากตารางบันทึกชนกัน</item>
+      <item quantity="one">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ซีรีส์อื่น 1 ตอนจะไม่มีการบันทึกเนื่องจากตารางบันทึกชนกัน</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_4">%2$s</xliff:g> ซีรีส์อื่น <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ตอนจะไม่มีการบันทึกเนื่องจากตารางบันทึกชนกัน</item>
+      <item quantity="one">กำหนดเวลาบันทึกแล้ว <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> รายการสำหรับ <xliff:g id="SERIESNAME_1">%2$s</xliff:g> ซีรีส์อื่น <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ตอนจะไม่มีการบันทึกเนื่องจากตารางบันทึกชนกัน</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"ไม่พบโปรแกรมที่บันทึกไว้"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"การบันทึกที่เกี่ยวข้อง"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(ไม่มีรายละเอียดรายการ)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">การบันทึก %1$d รายการ</item>
       <item quantity="one">การบันทึก %1$d รายการ</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"หยุดบันทึกซีรีส์ไหม"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"ตอนที่บันทึกไว้จะยังคงอยู่ในไลบรารี DVR"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"หยุด"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ไม่มีตอนใดออกอากาศในตอนนี้"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"ไม่มีตอนที่พร้อมรับชม\nระบบจะเริ่มบันทึกเมื่อมีตอนที่พร้อมรับชม"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d นาที)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> วันนี้"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> พรุ่งนี้"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"คะแนน"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"รายการที่บันทึกไว้"</string>
 </resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index a925aee..cc19b27 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Mga kontrol sa Play"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Kamakailang channel"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Mga Channel"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Opsyon sa TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Mga opsyon sa PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Hindi available para sa channel na ito ang mga kontrol ng laro"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"I-play o i-pause"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"I-fast forward"</string>
@@ -35,37 +34,19 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Closed captions"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Display mode"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Naka-on"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Naka-off"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Multi-audio"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Higit pa channel"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Mga Setting"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Pinagmulan"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Pagpalitin"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Naka-on"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Naka-off"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Tunog"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Pangunahin"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP window"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Layout"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Kanang ibaba"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Kanang itaas"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Kaliwang itaas"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Kaliwang ibaba"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Magkatabi"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Laki"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Malaki"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Maliit"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Pinagmulan ng input"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenna/cable)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Walang impormasyon ng programa"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Walang impormasyon"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Naka-block na channel"</string>
-    <string name="default_language" msgid="4122326459624337928">"Hindi kilalang wika"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Hindi kilalang wika"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Mga closed caption %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Mga closed caption"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Naka-off"</string>
-    <string name="closed_caption_system_settings" msgid="1856974607743827178">"Customize formatting"</string>
-    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"I-set kagustuhan para sa closed captions"</string>
+    <string name="closed_caption_system_settings" msgid="1856974607743827178">"I-customize ang pag-format"</string>
+    <string name="closed_caption_system_settings_description" msgid="6285276836057964524">"I-set ang kagustuhan sa closed captions para sa buong system"</string>
     <string name="side_panel_title_display_mode" msgid="6346286034015991229">"Display mode"</string>
     <string name="side_panel_title_multi_audio" msgid="5970537894780855080">"Multi-audio"</string>
     <string name="multi_audio_channel_mono" msgid="6229173848963557723">"mono"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Ipangkat ayon sa"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Naka-block ang programang ito"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Hindi na-rate ang programang ito"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Ang programang ito ay na-rate na <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Hindi sinusuportahan ng input ang auto-scan"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Hindi maumpisahan ang auto-scan para sa \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">Nagdagdag ng %1$d na channel</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Wala naidagdag na channel"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Parental controls"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Naka-on"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Naka-off"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Iba pang bansa"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Wala"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Wala"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Hindi na-rate"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"I-block ang mga programang hindi na-rate"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Wala"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"High restrictions"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Bahagyang pinaghihigpitan"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Ilagay iyong PIN upang mapanood ang channel na ito"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Ilagay iyong PIN upang mapanood ang programang ito"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"May rating na <xliff:g id="RATING">%1$s</xliff:g> ang programang ito. Ilagay ang iyong PIN upang mapanood ang programang ito"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Hindi na-rate ang programang ito. Ilagay ang iyong PIN upang mapanood ang programang ito"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Ilagay ang iyong PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Upang itakda ang mga parental control, gumawa ng PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Ilagay ang bagong PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Mali ang PIN na iyon. Subukang muli."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Subukang muli, hindi tumutugma ang PIN"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Ilagay ang iyong ZIP Code."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Gagamitin ng app na Mga Live Channel ang ZIP Code upang magbigay ng kumpletong gabay sa programa para sa mga channel sa TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Ilagay ang iyong ZIP Code"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Di-wasto ang ZIP Code"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Mga Setting"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"I-customize lista ng channel"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Pumili ng mga channel para sa gabay sa programa"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Mga pinagmulan ng channel"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"May mga bagong channel"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Mga kontrol ng magulang"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Mag-record habang nanonood upang ma-pause o ma-rewind mo ang mga live na programa.\nBabala: Maaari nitong mabawasan ang itatagal ng internal storage dahil sa labis-labis na paggamit ng storage."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Mga open source na lisensya"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Mga lisensyang open source"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Magpadala ng feedback"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Bersyon"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Upang mapanood ang channel na ito, pindutin ang Kanan at ilagay ang iyong PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Upang mapanood ang programang ito, pindutin ang Kanan at ilagay ang iyong PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Hindi na-rate ang programang ito.\nUpang mapanood ang programang ito, pindutin ang Kanan at ilagay ang iyong PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Ang programang ito ay na-rate na <xliff:g id="RATING">%1$s</xliff:g>.\nUpang mapanood ang programang ito, pindutin ang Kanan at ilagay ang iyong PIN."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Upang mapanood ang channel na ito, gamitin ang default na Live TV app."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Upang mapanood ang programang ito, gamitin ang default na Live TV app."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Hindi na-rate ang programang ito.\nUpang mapanood ang programang ito, gamitin ang default na Live TV app."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Ang programang ito ay binigyan ng rating na <xliff:g id="RATING">%1$s</xliff:g>.\nUpang mapanood ang programang ito, gamitin ang default na Live TV app."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Naka-block ang programa"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Hindi na-rate ang programang ito"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Ang programang ito ay na-rate na <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Audio lang"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Mahinang signal"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Pindutin ang SELECT"</b>" upang i-access ang menu ng TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Walang nahanap na TV input"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Hindi mahanap ang TV input"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"Hindi sinusuportahan ang PIP"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Walang available na input na maipapakita sa PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Hindi naaangkop ang uri ng tuner. Pakilunsad ang app na Mga Live na Channel para sa uri ng tuner na input ng TV."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Hindi na-tune"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Walang nakitang app na gagawa sa aksyong ito."</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d recording ang nakaiskedyul</item>
       <item quantity="other">%1$d na recording ang nakaiskedyul</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Kanselahin ang pag-record"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Ihinto ang pag-record"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Panoorin"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"I-play mula sa simula"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Ituloy ang pag-play"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Kapag masyadong maraming programa ang ire-record nang sabay-sabay, tanging ang may mas mataas na priyoridad lang ang mare-record."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"I-save"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Ang mga isang beses na pagre-record ang may pinakamataas na priyoridad"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Kanselahin"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Kanselahin"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Kalimutan"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Ihinto"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Tingnan, iskedyul ng recording"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Ang isang programang ito"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Ito na lang ang i-record"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Kanselahin ang pag-record na ito"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Panoorin ngayon"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"I-delete ang mga recording…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Mare-record"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Nakaiskedyul ang recording"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"May conflict sa pagre-record"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Nagre-record"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Hindi na-record"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Nagbabasa ng mga program upang makagawa ng mga iskedyul ng pagre-record"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Binabasa ang mga programa"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Binabasa ang mga programa"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Tingnan ang mga kamakailang recording"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Hindi natapos ang pag-record sa <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Hindi natapos ang mga pag-record sa <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> at <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Hindi natapos ang mga pag-record sa <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> at <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Hindi natapos ang pag-record sa <xliff:g id="PROGRAMNAME">%1$s</xliff:g> dahil sa hindi sapat na storage."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Hindi natapos ang mga pag-record sa <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> at <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> dahil sa hindi sapat na storage."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Hindi natapos ang mga pag-record sa <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> at <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> dahil sa hindi sapat na storage."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Kailangan ng DVR ng higit pang storage"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Makakapag-record ka ng mga program gamit ang DVR. Gayunpaman, walang sapat na storage sa iyong device ngayon upang gumana ang DVR. Mangyaring magkonekta ng external drive na <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB o mas malaki at sundin ang mga hakbang upang i-format ito bilang storage ng device."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Makakapag-record ka ng mga program gamit ang DVR. Gayunpaman, walang sapat na storage sa iyong device ngayon upang gumana ang DVR. Mangyaring magkonekta ng external drive na <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB o mas malaki at sundin ang mga hakbang upang i-format ito bilang storage ng device."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Hindi sapat ang storage"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Hindi mare-record ang program na ito dahil walang sapat na storage. Subukang mag-delete ng ilang dati nang recording."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Nawawala ang storage"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"May nawawalang bahagi ng storage na ginagamit ng DVR. Pakikonekta ang external na drive na ginamit mo dati upang muling i-enable ang DVR. O kaya, maaari mo ring piliing kalimutan ang storage kung hindi na ito available."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Kalimutan ang storage?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Mawawala ang lahat ng na-record mong content at iskedyul."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Ihinto ang pagre-record?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Mase-save ang na-record na content."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Ihihinto na ang pag-record ng <xliff:g id="PROGRAMNAME">%1$s</xliff:g> dahil kasabay ito ng palabas na ito. Ise-save ang na-record na content."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Naiskedyul na ang pagre-record ngunit may mga hindi pagkakatugma"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Nagsimula na ang pagre-record ngunit may mga hindi pagkakatugma"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Mare-record ang <xliff:g id="PROGRAMNAME">%1$s</xliff:g>."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Naiskedyul na ang parehong programa na ma-record sa <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Na-record na"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Na-record na ang programang ito. Available ito sa DVR library."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Naiskedyul na ang pag-record ng series"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recording ang naiskedyul para sa <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> na recording ang naiskedyul para sa <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recording ang naiskedyul para sa <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Hindi mare-record ang <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> sa mga ito dahil sa may mga nakaiskedyul na.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> na recording ang naiskedyul para sa <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. Hindi mare-record ang <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> sa mga ito dahil sa may mga nakaiskedyul na.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recording ang naiskedyul para sa <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episode ng series na ito at ng iba pang series ang hindi mare-record dahil may mga nakaiskedyul na.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> na recording ang naiskedyul para sa <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> na episode ng series na ito at ng iba pang series ang hindi mare-record dahil may mga nakaiskedyul na.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> recording ang naiskedyul para sa <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episode ng iba pang series ang hindi mare-record dahil sa may mga nakaiskedyul na.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> na recording ang naiskedyul para sa <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 episode ng iba pang series ang hindi mare-record dahil sa may mga nakaiskedyul na.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> recording ang naiskedyul para sa <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> episode ng iba pang series ang hindi mare-record dahil sa may mga nakaiskedyul na.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> na recording ang naiskedyul para sa <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> na episode ng iba pang series ang hindi mare-record dahil sa may mga nakaiskedyul na.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Hindi nakita ang na-record na programa."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Mga nauugnay na recording"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Walang paglalarawan ng program)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d recording</item>
       <item quantity="other">%1$d na recording</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Gusto mo bang ihinto ang pagre-record ng mga serye?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Mananatiling available sa library ng DVR ang mga na-record na episode."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Ihinto"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Walang ipinapalabas na episode ngayon."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Walang available na mga episode.\nMare-record ang mga ito kapag available na ang mga ito."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d minuto)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ngayong araw"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> bukas"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Marka"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Mga Na-record na Programa"</string>
 </resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 8162fbf..d8f92210 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Oynatma denetimleri"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Son kanallar"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanallar"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV seçenekleri"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP seçenekleri"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Bu kanal için oynatma denetimleri kullanılamıyor"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Oynat veya duraklat"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"İleri sar"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Altyazılar"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Görüntü modu"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Açık"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Kapalı"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Çoklu ses"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Daha çok kanal al"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Ayarlar"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Kaynak"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Değiştir"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Açık"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Kapalı"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Ses"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Ana"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP penceresi"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Düzen"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Sağ alt"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Sağ üst"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Sol üst"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Sol alt"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Yan yana"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Boyut"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Büyük"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Küçük"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Giriş kaynağı"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (anten/kablo)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Hiçbir program bilgisi yok"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Bilgi yok"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Engellenen kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Bilinmeyen dil"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Bilinmeyen dil"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Altyazılar %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Altyazılar"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Kapalı"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Biçimi özelleştir"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Gruplama ölçütü"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Bu program engellendi"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Bu program derecelendirilmedi"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Bu program <xliff:g id="RATING">%1$s</xliff:g> olarak derecelendirilmiştir"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Giriş, otomatik taramayı desteklemiyor"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\"<xliff:g id="TV_INPUT">%s</xliff:g>\" için otomatik tarama başlatılamıyor"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">%1$d kanal eklendi</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Hiçbir kanal eklenmedi"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Ebeveyn denetimi"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Açık"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Kapalı"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Diğer ülkeler"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Yok"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Yok"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Derecelendirilmedi"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Derecelendirilmemiş programları engelle"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Yok"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Yüksek kısıtlama"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Orta düzey kısıtlama"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Bu kanalı izlemek için PIN\'inizi girin"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Bu programı izlemek için PIN\'inizi girin"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Bu program <xliff:g id="RATING">%1$s</xliff:g> olarak derecelendirildi. Bu programı izlemek için PIN kodunuzu girin."</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Bu program derecelendirilmedi. Programı izlemek için PIN kodunuzu girin."</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PIN\'inizi girin"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Ebeveyn denetimlerini ayarlamak için PIN oluşturun"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Yeni PIN\'i girin"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Girdiğiniz PIN hatalıydı. Tekrar deneyin."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Tekrar deneyin, PIN eşleşmiyor"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Posta Kodunuzu girin."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Canlı Kanallar uygulaması, TV kanalları için eksiksiz bir program rehberi sunmak üzere Posta Kodu\'nu kullanacaktır."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Posta Kodunuzu girin"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Geçersiz Posta Kodu"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Ayarlar"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Kanal listesini özelleştir"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Program rehberiniz için kanalları seçin"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanal kaynakları"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Yeni kanallar mevcut"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Ebeveyn denetimleri"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Zaman kaydırma"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"İzlerken kaydedin. Böylece canlı programları duraklatabilir veya geri sarabilirsiniz. \nUyarı: Bu özellik depolama alanını yoğun bir şekilde kullandığından dahili depolama alanının kullanım ömrü azalabilir."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Açık kaynak lisansları"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Açık kaynak lisansları"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Geri bildirim gönder"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Sürüm"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Bu kanalı izlemek için Sağ tuşuna basın ve PIN\'inizi girin"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Bu programı izlemek için Sağ tuşuna basın ve PIN\'inizi girin"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Bu program derecelendirilmedi.\nProgramı izlemek için Sağ\'a basın ve PIN\'inizi girin."</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Bu program <xliff:g id="RATING">%1$s</xliff:g> olarak derecelendirilmiştir.\nBu programı izlemek için Sağ tuşuna basın ve PIN\'inizi girin."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Bu kanalı izlemek için varsayılan Canlı TV uygulamasını kullanın."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Bu programı izlemek için varsayılan Canlı TV uygulamasını kullanın."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Bu program derecelendirilmedi.\nProgramı izlemek için varsayılan Canlı TV uygulamasını kullanın."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Bu program <xliff:g id="RATING">%1$s</xliff:g> olarak derecelendirildi.\nBu programı izlemek için varsayılan Canlı TV uygulamasını kullanın."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Program engellendi"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Bu program derecelendirilmedi"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Bu program <xliff:g id="RATING">%1$s</xliff:g> olarak derecelendirilmiştir"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Yalnızca ses"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Zayıf sinyal"</string>
@@ -171,7 +164,7 @@
     <string name="setup_input_new" msgid="3337725672277046798">"Yeni"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Yapılandırılmadı"</string>
     <string name="setup_store_action_title" msgid="4083402039720973414">"Daha fazla kaynak al"</string>
-    <string name="setup_store_action_description" msgid="6820482635042445297">"Canlı kanallar sunan uygulamalara göz atın"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Canlı kanal uygulamalarına göz atın"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"Kullanılabilir yeni kanal kaynakları mevcut"</string>
     <string name="new_sources_description" msgid="749649005588426813">"Yeni kanal kaynaklarında sunulan kanallar var.\nBunları şimdi ayarlayın veya daha sonra kanal kaynakları ayarında yapılandırın."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Şimdi ayarla"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"TV menüsüne erişmek için "<b>"SEÇ\'e basın"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"TV girişi bulunamadı"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV girişi bulunamadı"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP desteklenmiyor"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP ile göstermeye uygun giriş yok"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Kanal tarayıcı türü uygun değil. TV girişi kanal tarayıcı türü için lütfen Canlı Yayın Kanalları uygulamasını başlatın."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Tarama işlemi başarısız oldu"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Bu işlemi gerçekleştirecek uygulama bulunamadı."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d kayıt planlandı</item>
       <item quantity="one">%1$d kayıt planlandı</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Kaydı iptal et"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Kaydı durdur"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"İzle"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Baştan oynat"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Oynatmaya devam et"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Aynı anda kaydedilecek çok sayıda program olduğundan, yalnızca yüksek öncelikli programlar kaydedilir."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Kaydet"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Bir kerelik kayıtlar en yüksek önceliğe sahip"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"İptal"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"İptal"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Unut"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Durdur"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Kayıt programını görüntüle"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Yalnızca bu program"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Onun yerine bunu kaydet"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Bu kaydı iptal et"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Şimdi izle"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Kayıtları sil…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Kaydedilebilir"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Kayıt programlandı"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Kayıt çakışması"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Kaydediliyor"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Kaydedilemedi"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Kayıt planlarını oluşturmak için programlar okunuyor"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Program bilgisi okunuyor"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Program bilgisi okunuyor"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Son kayıtları görüntüleyin"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> kaydı tam değil."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ve <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> kayıtları tam değil."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ve <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> kayıtları tam değil."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Kullanılabilir depolama alanı yeterli olmadığından <xliff:g id="PROGRAMNAME">%1$s</xliff:g> kaydı tamamlanamadı."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Kullanılabilir depolama alanı yeterli olmadığından <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ve <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> kayıtları tamamlanamadı."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Kullanılabilir depolama alanı yeterli olmadığından <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ve <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> kayıtları tamamlanamadı."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR için daha fazla depolama alanı gerekiyor"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Programları DVR ile kaydedebileceksiniz. Ancak şu anda cihazınızda DVR\'nin çalışması için yeterli miktarda boş depolama alanı yok. Lütfen <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB veya daha büyük kapasiteye sahip harici sürücü bağlayın ve bu sürücüyü cihaz depolama alanı olarak biçimlendirmek için adımları uygulayın."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Programları DVR ile kaydedebileceksiniz. Ancak şu anda cihazınızda DVR\'nin çalışması için yeterli miktarda boş depolama alanı yok. Lütfen <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB veya daha büyük kapasiteye sahip harici sürücü bağlayın ve bu sürücüyü cihaz depolama alanı olarak biçimlendirmek için adımları uygulayın."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Yeterli depolama alanı yok"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Yeterli depolama alanı olmadığı için bu program kaydedilmeyecek. Mevcut kayıtlardan bazılarını silmeyi deneyin."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Kayıp depolama birimi"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"DVR tarafından kullanılan bazı depolama alanları kayıp. DVR\'yi yeniden etkinleştirmeden önce lütfen kullandığınız harici sürücüyü bağlayın. Ayrıca bu depolama alanı artık kullanılmıyorsa unutulmasını da seçebilirsiniz."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Depolama alanı unutulsun mu?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Kaydedilen tüm içeriğiniz ve programlarınız kaybolacaktır."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Kayıt durudurulsun mu?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Kaydedilen içerik saklanacak."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> kaydı, bu programla çakıştığından durdurulacak. Kaydedilen içerik saklanacak."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Kayıt programlandı, ancak çakışmalar var"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Kayıt işlemi başladı, ancak çakışmalar var"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> kaydedilecek."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Aynı program şu tarihte ve saatte kaydedilecek şekilde zaten programlandı: <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Zaten kaydedildi"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Bu program zaten kaydedildi. DVR kitaplığında bulabilirsiniz."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Dizi kaydı programlandı"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> kayıt programlandı.</item>
+      <item quantity="one"> <xliff:g id="SERIESNAME_1">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> kayıt programlandı.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> kayıt programlandı. Çakışma nedeniyle bu kayıtların <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> tanesi yapılmayacak.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> kayıt programlandı. Çakışma nedeniyle bu kayıt yapılmayacak.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> kayıt programlandı. Çakışma nedeniyle bu dizinin ve diğer dizilerin <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> bölümü kaydedilmeyecek.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> kayıt programlandı. Çakışma nedeniyle bu dizinin ve diğer dizilerin <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> bölümü kaydedilmeyecek.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> kayıt programlandı. Çakışma nedeniyle diğer dizinin 1 bölümü kaydedilmeyecek.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> kayıt programlandı. Çakışma nedeniyle diğer dizinin 1 bölümü kaydedilmeyecek.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> kayıt programlandı. Çakışma nedeniyle diğer dizinin <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> bölümü kaydedilmeyecek.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> için <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> kayıt programlandı. Çakışma nedeniyle diğer dizinin <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> bölümü kaydedilmeyecek.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Kaydedilen program bulunamadı."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"İlgili kayıtlar"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Program açıklaması yok)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d kayıt</item>
       <item quantity="one">%1$d kayıt</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Dizinin kaydı durdurulsun mu?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Kaydedilen bölümler DVR kitaplığında kalmaya devam edecektir."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Durdur"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Şu anda yayınlanan bir bölüm yok."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Kaydedilebilecek bir bölüm yok.\nBölümler kullanıma sunulduğunda kaydedilecektir."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d dakika)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Bugün <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Yarın <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Puanı"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Kayıtlı Programlar"</string>
 </resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index b9d91a7..1d673df 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"моно"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"стерео"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Керування відтворенням"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Останні канали"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Канали"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Опції ТБ"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Опції PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Елементи керування відтворенням, яких немає в цьому каналі"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Відтворити або призупинити"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Перемотати вперед"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Субтитри"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Режим показу"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Увімкнено"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Вимкнено"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Кілька аудіо"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Більше каналів"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Налаштування"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Джерело"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Заміна"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Увімкнено"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Вимкнено"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Звук"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Основне вікно"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Вікно PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Схема"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Унизу праворуч"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Угорі праворуч"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Угорі ліворуч"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Унизу ліворуч"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Поруч"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Розмір"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Великий розмір"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Малий розмір"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Джерело сигналу"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"ТБ (ефірне або кабельне)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Немає інформації про програму"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Немає інформації."</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Заблокований канал"</string>
-    <string name="default_language" msgid="4122326459624337928">"Невідома мова"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Невідома мова"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Субтитри (%1$d)"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Субтитри"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Вимкнути"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Налаштувати формат"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Параметри групування"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Цю телепередачу заблоковано"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Ця передача без вікових обмежень"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Ця телепередача належить до категорії <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Джерело вхідного сигналу не підтримує автоматичне сканування"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Не вдалось автоматично просканувати джерело сигналу \"<xliff:g id="TV_INPUT">%s</xliff:g>\""</string>
@@ -94,7 +76,6 @@
       <item quantity="other">Додано %1$d каналу</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Немає каналів"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Тюнер"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Контроль батьків"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Увімкнути"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Вимкнути"</string>
@@ -110,6 +91,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Інші країни"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Немає"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Немає"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Без вікових обмежень"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Блокувати передачі без вікових обмежень"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Немає"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Суворі обмеження"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Помірні обмеження"</string>
@@ -126,6 +109,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Введіть PIN-код, щоб дивитися цей канал"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Введіть PIN-код, щоб дивитися цю телепередачу"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Вікові обмеження для цієї передачі: <xliff:g id="RATING">%1$s</xliff:g>. Щоб дивитися її, введіть PIN-код"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Це передача без вікових обмежень. Щоб дивитися її, введіть PIN-код"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Введіть PIN-код"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Щоб налаштувати батьківський контроль, створіть PIN-код"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Введіть новий PIN-код"</string>
@@ -139,22 +123,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Цей PIN-код неправильний. Повторіть спробу."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN-коди не збігаються. Повторіть спробу"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Введіть поштовий індекс."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Додаток Телеканали показує повну програму телепередач на основі поштового індексу."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Введіть поштовий індекс"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Недійсний поштовий індекс"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Налаштування"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Налаштувати список каналів"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Вибрати канали для програми телепередач"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Джерела каналів"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Доступні нові канали"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Батьківський контроль"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Зміщення в часі"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Записуйте передачі під час перегляду, щоб потім призупиняти або перемотувати їх.\nЗастереження. Це може зменшити обсяг внутрішньої пам’яті через її інтенсивне використання."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Ліцензії відкритого коду"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Ліцензії ПЗ з відкритим кодом"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Надіслати відгук"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Версія"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Щоб дивитися цей канал, натисніть стрілку праворуч і введіть PIN-код"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Щоб дивитися цю телепередачу, натисніть стрілку праворуч і введіть PIN-код"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Це передача без вікових обмежень.\nЩоб дивитися її, натисніть стрілку вправо та введіть PIN-код"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Ця телепередача належить до категорії <xliff:g id="RATING">%1$s</xliff:g>.\nЩоб дивитися її, натисніть стрілку праворуч і введіть PIN-код."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Щоб дивитися цей канал, відкрийте додаток для прямих трансляцій за умовчанням."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Щоб дивитися цю телепередачу, відкрийте додаток для прямих трансляцій за умовчанням."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Це передача без вікових обмежень.\nЩоб дивитися її, відкрийте додаток для прямих трансляцій за умовчанням."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Категорія цієї телепередачі – <xliff:g id="RATING">%1$s</xliff:g>.\nЩоб дивитися її, відкрийте додаток для прямих трансляцій за умовчанням."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Телепередачу заблоковано"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Ця передача без вікових обмежень"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Ця телепередача належить до категорії <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Лише аудіо"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Слабкий сигнал"</string>
@@ -179,7 +172,7 @@
     <string name="setup_input_new" msgid="3337725672277046798">"Нові"</string>
     <string name="setup_input_setup_now" msgid="1772000402336958967">"Не налаштовано"</string>
     <string name="setup_store_action_title" msgid="4083402039720973414">"Отримати більше джерел"</string>
-    <string name="setup_store_action_description" msgid="6820482635042445297">"Переглянути додатки, у яких пропонуються канали в прямому ефірі"</string>
+    <string name="setup_store_action_description" msgid="6820482635042445297">"Переглянути додатки, у яких можна дивитися телеканали в прямому ефірі"</string>
     <string name="new_sources_title" msgid="3878933676500061895">"Доступні нові джерела каналів"</string>
     <string name="new_sources_description" msgid="749649005588426813">"Нові джерела пропонують канали.\nНалаштуйте їх зараз або зробіть це пізніше в налаштуваннях джерел каналів."</string>
     <string name="new_sources_action_setup" msgid="177693761664016811">"Налаштувати"</string>
@@ -189,8 +182,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Натисніть \"ВИБРАТИ\""</b>", щоб відкрити меню телевізора."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Не знайдено джерел вхідного телесигналу"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Не вдається знайти джерело вхідного телесигналу"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP не підтримується"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Немає джерел вхідного сигналу для PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Тюнер не підтримується. Щоб використовувати тюнер, запустіть додаток Live TV."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Не вдалося налаштувати"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Не знайдено додатка для цієї дії."</string>
@@ -199,7 +190,7 @@
     <string name="msg_back_key_guide" msgid="7404682718828721924">"Клавіша \"НАЗАД\" діє на підключеному пристрої. Натисніть \"ГОЛОВНИЙ ЕКРАН\", щоб вийти."</string>
     <string name="msg_read_tv_listing_permission_denied" msgid="8882813301235518909">"Додатку Live TV потрібен дозвіл переглядати програму телепередач."</string>
     <string name="setup_sources_text" msgid="4988039637873759839">"Налаштуйте джерела"</string>
-    <string name="setup_sources_description" msgid="5695518946225445202">"У телеканалах поєднуються зручність традиційних каналів і трансляція каналів із додатків. \n\nЩоб почати, налаштуйте вже встановлені джерела каналів. Або пошукайте в магазині Google Play інші додатки з телеканалами."</string>
+    <string name="setup_sources_description" msgid="5695518946225445202">"Телеканали об\'єднують звичайні канали й потокові трансляції з додатків. \n\nПочніть із налаштування вже наявних джерел каналів або пошукайте в магазині Google Play інші додатки з телеканалами."</string>
     <string name="channels_item_dvr" msgid="8911915252648532469">"Записи та графіки"</string>
     <string name="recording_start_dialog_10_min_duration" msgid="5739636508245795292">"10 хвилин"</string>
     <string name="recording_start_dialog_30_min_duration" msgid="4691127772622189977">"30 хвилин"</string>
@@ -244,6 +235,8 @@
       <item quantity="many">Заплановано %1$d записів</item>
       <item quantity="other">Заплановано %1$d запису</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Скасувати запис"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Припинити запис"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Переглянути"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Відтворити з початку"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Відновити відтворення"</string>
@@ -278,9 +271,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Якщо є забагато програм для одночасного запису, записуватимуться лише програми з вищим пріоритетом."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Зберегти"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Одноразові записи мають найвищий пріоритет"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Скасувати"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Скасувати"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Забути"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Припинити"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Переглянути розклад запису"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Лише ця передача"</string>
@@ -290,25 +280,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Натомість записати цю передачу"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Скасувати цей запис"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Дивитися"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Видалити записи…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Можна записати"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Запис заплановано"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Конфлікт запису"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Запис"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Не записано"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Читаються назви передач для створення розкладів"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Читання даних програм"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Читання інформації про передачі"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Переглянути нещодавні записи"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Запис передачі \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" не завершено."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Запис передач \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\" і \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" не завершено."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Запис передач \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\", \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" і \"<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>\" не завершено."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Запис передачі \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" не завершено. Замало місця."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Запис передач \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\" і \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" не завершено. Замало місця."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Запис передач \"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>\", \"<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>\" і \"<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>\" не завершено. Замало місця."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"Пристрою DVR потрібно більше пам’яті"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"За допомогою пристрою DVR можна записувати програми, однак на ньому недостатньо пам’яті. Підключіть зовнішній диск ємністю <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> Гб або більше та дотримуйтеся вказівок, щоб відформатувати його як пам’ять пристрою."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"За допомогою пристрою DVR можна записувати програми, однак на ньому недостатньо пам’яті. Підключіть зовнішній диск ємністю <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> ГБ або більше та дотримуйтеся вказівок, щоб відформатувати його як пам’ять пристрою."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Замало пам’яті"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Замало пам’яті. Цю передачу не буде записано. Спробуйте видалити деякі наявні записи."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Немає пам’яті"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Немає деякої пам’яті, яку використовує DVR. Щоб знову ввімкнути DVR, під’єднайте зовнішній диск, який ви використовували раніше. Можна також забути пам’ять, якщо вона недоступна."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Забути пам’ять?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Увесь записаний вміст і розклади буде втрачено."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Припинити запис?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Записаний вміст буде збережено."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Запис серіалу \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" буде зупинено через конфлікти з ним. Записаний вміст буде збережено."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Запис заплановано, однак є конфлікти"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Запис почався, однак є конфлікти"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"Програму \"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>\" буде записано."</string>
@@ -328,17 +321,39 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Цю передачу вже заплановано записати о <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Уже записано"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Цю передачу вже записано. Вона доступна в бібліотеці DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Заплановано запис серіалу"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запис серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\".</item>
+      <item quantity="few">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\".</item>
+      <item quantity="many">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записів серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\".</item>
+      <item quantity="other">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запису серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\".</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запис серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Через конфлікти не буде записано <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> із них.</item>
+      <item quantity="few">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Через конфлікти не буде записано <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> з них.</item>
+      <item quantity="many">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записів серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Через конфлікти не буде записано <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> із них.</item>
+      <item quantity="other">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запису серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Через конфлікти не буде записано <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> із них.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one">Заплановано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> запис серіалу \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Через конфлікти не буде записано стільки серій цього й іншого серіалів: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="few">Заплановано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записи серіалу \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Через конфлікти не буде записано стільки серій цього й іншого серіалів: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="many">Заплановано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записів серіалу \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Через конфлікти не буде записано стільки серій цього й іншого серіалів: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="other">Заплановано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> запису серіалу \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Через конфлікти не буде записано стільки серій цього й іншого серіалів: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запис серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Через конфлікти не буде записано 1 серію іншого серіалу.</item>
+      <item quantity="few">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записи серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Через конфлікти не буде записано 1 серію іншого серіалу.</item>
+      <item quantity="many">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> записів серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Через конфлікти не буде записано 1 серію іншого серіалу.</item>
+      <item quantity="other">Заплановано <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> запису серіалу \"<xliff:g id="SERIESNAME_3">%2$s</xliff:g>\". Через конфлікти не буде записано 1 серію іншого серіалу.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one">Заплановано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> запис серіалу \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Через конфлікти не буде записано стільки серій іншого серіалу: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="few">Заплановано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записи серіалу \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Через конфлікти не буде записано стільки серій іншого серіалу: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="many">Заплановано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> записів серіалу \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Через конфлікти не буде записано стільки серій іншого серіалу: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+      <item quantity="other">Заплановано <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> запису серіалу \"<xliff:g id="SERIESNAME_4">%2$s</xliff:g>\". Через конфлікти не буде записано стільки серій іншого серіалу: <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g>.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Не вдалося знайти записані програми."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Пов’язані записи"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Немає опису програми)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d запис</item>
       <item quantity="few">%1$d записи</item>
@@ -362,6 +377,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Припинити запис серій?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Записані серії можна переглянути в бібліотеці DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Припинити"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Зараз серії не транслюються."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Немає серій.\nСерії буде записано, щойно вони з’являться."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d хвилина)</item>
@@ -375,4 +391,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Сьогодні о <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Завтра о <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Оцінка"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Записані передачі"</string>
 </resources>
diff --git a/res/values-ur-v23/strings.xml b/res/values-ur-rPK-v23/strings.xml
similarity index 100%
rename from res/values-ur-v23/strings.xml
rename to res/values-ur-rPK-v23/strings.xml
diff --git a/res/values-ur/arrays.xml b/res/values-ur-rPK/arrays.xml
similarity index 100%
rename from res/values-ur/arrays.xml
rename to res/values-ur-rPK/arrays.xml
diff --git a/res/values-ur/rating_system_strings.xml b/res/values-ur-rPK/rating_system_strings.xml
similarity index 100%
rename from res/values-ur/rating_system_strings.xml
rename to res/values-ur-rPK/rating_system_strings.xml
diff --git a/res/values-ur/strings.xml b/res/values-ur-rPK/strings.xml
similarity index 78%
rename from res/values-ur/strings.xml
rename to res/values-ur-rPK/strings.xml
index 47fcb2a..36fed92 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"مونو"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"اسٹیریو"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"پلے کنٹرولز"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"حالیہ چینلز"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"چینلز"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"‏TV کے اختیارات"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"‏PIP کے اختیارات"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"چلانے کے کنٹرولز اس چینل کیلئے غیر دستیاب ہیں"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"چلائیں یا موقوف کریں"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"تیزی سے فارورڈ کریں"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"سب ٹائٹلز"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"ڈسپلے وضع"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"آن"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"آف"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"کثیر آڈیو"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"مزید چینلز حاصل کریں"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"ترتیبات"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"ماخذ"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"تبادلہ کریں"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"آن"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"آف"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"آواز"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"مرکزی"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"‏PIP ونڈو"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"لے آؤٹ"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"نیچے دائیں"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"اوپری دائیں"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"اوپری بائیں"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"نیچے بائیں"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"سمت بہ سمت"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"سائز"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"بڑا"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"چھوٹا"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"ان پٹ ماخذ"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"‏TV (اینٹینا/کیبل)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"پروگرام کی معلومات نہیں"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"کوئی معلومات نہیں ہے"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"مسدود چینل"</string>
-    <string name="default_language" msgid="4122326459624337928">"نامعلوم زبان"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"نامعلوم زبان"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"‏سب ٹائٹلز ‎%1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"سب ٹائٹلز"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"آف"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"فارمیٹنگ کسٹمائز کریں"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"گروپ بلحاظ"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"یہ پروگرام مسدود ہے"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"یہ پروگرام درجہ بند نہیں ہے"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"اس پروگرام کی درجہ بندی <xliff:g id="RATING">%1$s</xliff:g> کی گئی ہے"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"ان پٹ آٹو اسکین کو سپورٹ نہیں کرتا"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"\'<xliff:g id="TV_INPUT">%s</xliff:g>\' کیلئے آٹو اسکین شروع کرنے سے قاصر ہے"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">‏%1$d چینل شامل ہو گیا</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"کوئی چینلز شامل نہیں کیے گئے"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"ٹیونر"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"پیرنٹل کنٹرولز"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"آن"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"آف"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"دیگر ممالک"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"کوئی نہیں"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"کوئی نہیں"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"غیر درجہ بند"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"غیردرجہ بند پروگرام مسدود کریں"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"کوئی نہیں"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"زیادہ پابندیاں"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"متوسط پابندیاں"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"‏یہ چینل دیکھنے کیلئے اپنا PIN درج کریں"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"‏یہ پروگرام دیکھنے کیلئے اپنا PIN درج کریں"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"‏اس پروگرام کی درجہ بندی <xliff:g id="RATING">%1$s</xliff:g> ہوئی ہے۔ اس پروگرام کو دیکھنے کیلئے اپنی PIN درج کریں"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"‏یہ پروگرام درجہ بند نہیں ہے۔ اس پروگرام کو دیکھنے کے لیے اپنا PIN درج کریں"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"‏اپنا PIN درج کریں"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"‏پیرنٹل کنٹرولز سیٹ کرنے کیلئے، ایک PIN بنائیں"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"‏نیا PIN درج کریں"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"‏وہ PIN غلط تھا۔ دوبارہ کوشش کریں۔"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"‏دوبارہ کوشش کریں، PIN مماثل نہیں ہے"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"اپنا زپ کوڈ درج کریں۔"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"‏لائیو چینلز ایپ TV چینلز کیلئے ایک مکمل پروگرام گائیڈ فراہم کرنے کیلئے زپ کوڈ استعمال کرے گی۔"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"اپنا زپ کوڈ درج کریں"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"غلط زپ کوڈ"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"ترتیبات"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"چینل فہرست حسب ضرورت بنائیں"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"اپنی پروگرام گائیڈ کیلئے چینلز منتخب کریں"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"چینل کے مآخذ"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"نئے چینلز دستیاب ہیں"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"پیرنٹل کنٹرولز"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"ٹائم شفٹ"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"دیکھنے کے دوران ریکارڈ کریں تاکہ آپ لائیو پروگرامز کو موقوف یا ریوائنڈ کر سکیں۔\nتنبیہ: اس کے باعث اسٹوریج کے بے تحاشا استعمال کی وجہ سے شاید اندرونی اسٹوریج کی زندگی کم ہو جائے۔"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"اوپن سورس لائسنسز"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"اوپن سورس لائسنسز"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"تاثرات بھیجیں"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"ورژن"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"‏یہ چینل دیکھنے کیلئے Right دبائیں اور اپنا PIN درج کریں"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"‏یہ پروگرام دیکھنے کیلئے Right دبائیں اور اپنا PIN درج کریں"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"‏یہ پروگرام درجہ بند نہیں ہے۔\nاس پروگرام کو دیکھنے کے لیے، دائیں جانب دبا کر اپنا PIN درج کریں"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"‏اس پروگرام کی درجہ بندی <xliff:g id="RATING">%1$s</xliff:g> کی گئی ہے۔\nاس پروگرام کو دیکھنے کیلئے Right دبائیں اور اپنا PIN درج کریں"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"‏اس چینل کو دیکھنے کیلئے ڈیفالٹ لائیو TV ایپ استعمال کریں۔"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"‏اس پروگرام کو دیکھنے کیلئے ڈیفالٹ لائیو TV ایپ استعمال کریں۔"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"‏یہ پروگرام درجہ بند نہیں ہے۔\nاس پروگرام کو دیکھنے کے لیے، ڈیفالٹ لائیو TV ایپ استعمال کریں۔"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"‏اس پروگرام کی درجہ بندی <xliff:g id="RATING">%1$s</xliff:g> کی گئی ہے۔\nاس پروگرام کو دیکھنے کیلئے ڈیفالٹ لائیو TV ایپ استعمال کریں۔"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"پروگرام مسدود ہے"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"یہ پروگرام درجہ بند نہیں ہے"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"اس پروگرام کی درجہ بندی <xliff:g id="RATING">%1$s</xliff:g> کی گئی ہے"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"صرف آڈیو"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"کمزور سگنل"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"‏TV مینو تک رسائی حاصل کرنے کیلئے "<b>"منتخب کریں کو دبائیں"</b>"۔"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"‏کوئی TV ان پٹ نہیں ملا"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"‏TV ان پٹ تلاش نہیں کیا جا سکتا"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"‏PIP تعاون یافتہ نہیں ہے"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"‏ایسا کوئی ان پٹ دستیاب نہیں ہے جسے PIP کے ساتھ دکھایا جا سکے"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"‏ٹیونر کی قسم مناسب نہیں ہے۔ براہ کرم ٹیونر کی قسم والے TV ان پٹ کیلئے لائیو چینلز ایپ شروع کریں۔"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"ٹیون کرنا ناکام ہوگیا"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"اس کارروائی کو نمٹانے کیلئے کوئی ایپ نہیں ملی۔"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">‏%1$d ریکارڈنگز کا شیڈول بن گیا</item>
       <item quantity="one">‏%1$d ریکارڈنگ کا شیڈول بن گيا</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"ریکارڈنگ منسوخ کریں"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"ریکارڈنگ روکیں"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"دیکھیں"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"شروع سے چلائیں"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"چلانا دوبارہ شروع کریں"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"جب ایک وقت میں بہت سارے پروگرامز ریکارڈ کرنے ہوں تو صرف اعلی ترجیح والے پروگرامز ریکارڈ کیے جائیں گے۔"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"محفوظ کریں"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"یک وقتی ریکارڈنگز کو سب سے اعلی ترجیح حاصل ہوتی ہے"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"منسوخ کریں"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"منسوخ کریں"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"بھول جائیں"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"روکیں"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"ریکارڈنگ کا شیڈول ملاحظہ کریں"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"یہ واحد پروگرام"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"اس کی بجائے یہ ریکارڈ کریں"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"اس ریکارڈنگ کو منسوخ کریں"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"ابھی دیکھیں"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"ریکارڈنگز حذف کریں…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"قابل ریکارڈ"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"ریکارڈنگ کا شیڈول"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"ریکارڈنگ شیڈول میں تصادم"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"ریکارڈ ہو رہا ہے"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"ریکارڈنگ ناکام ہو گئی"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"ریکارڈنگ کے شیڈولز بنانے کیلئے پروگرام پڑھے جا رہے ہیں"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"پروگرامز پڑھے جا رہے ہیں"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"پروگرامز پڑھے جا رہے ہیں"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"حالیہ ریکارڈنگز ملاحظہ کریں"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> کی ریکارڈنگ نامکمل ہے۔"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> اور <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> کی ریکارڈنگز نامکمل ہیں۔"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>، <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> اور <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> کی ریکارڈنگز نامکمل ہیں۔"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"ناکافی اسٹوریج کی وجہ سے <xliff:g id="PROGRAMNAME">%1$s</xliff:g> کی ریکارڈنگ مکمل نہیں ہوئی۔"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"ناکافی اسٹوریج کی وجہ سے <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> اور <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> کی ریکارڈنگز مکمل نہیں ہوئیں۔"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"ناکافی اسٹوریج کی وجہ سے <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>، <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> اور <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> کی ریکارڈنگز مکمل نہیں ہوئیں۔"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"‏DVR کو مزید اسٹوریج درکار ہے"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"‏آپ DVR کے ساتھ پروگرامز ریکارڈ کر سکیں گے۔ تاہم آپ کے آلہ پر DVR کے کام کرنے کیلئے ابھی کافی اسٹوریج نہیں ہے۔ براہ کرم ایک بیرونی ڈرائیو منسلک کریں جو GB <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> یا اس سے بڑی ہو اور اسے آلہ کی اسٹوریج کے بطور فارمیٹ کرنے کیلئے مراحل کی پیروی کریں۔"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"‏آپ DVR کے ساتھ پروگرامز ریکارڈ کر سکیں گے۔ تاہم آپ کے آلہ پر DVR کے کام کرنے کیلئے ابھی کافی اسٹوریج نہیں ہے۔ براہ کرم ایک بیرونی ڈرائیو منسلک کریں جو GB <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> یا اس سے بڑی ہو اور اسے آلہ کی اسٹوریج کے بطور فارمیٹ کرنے کیلئے مراحل کی پیروی کریں۔"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"اسٹوریج کافی نہیں ہے"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"یہ پروگرام ریکارڈ نہیں ہوگا کیونکہ اسٹوریج کافی نہیں ہے۔ کچھ موجودہ ریکارڈنگز حذف کرنے کی کوشش کریں۔"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"اسٹوریج غائب ہے"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"‏DVR کی استعمال کردہ کچھ اسٹوریج غائب ہے۔ براہ کرم وہ بیرونی ڈرائیو جو آپ نے پہلے DVR کو دوبارہ فعال کرنے کیلئے استعمال کی تھی، منسلک کریں۔ متبادل طور پر، اگر یہ مزید دستیاب نہ ہو تو آپ اسٹوریج کو بھولنے کا انتخاب کر سکتے ہیں۔"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"اسٹوریج کو بھول جائیں؟"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"آپ کا تمام ریکارڈ کردہ مواد اور شیڈولز ضائع ہو جائیں گے۔"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"ریکارڈنگ روکیں؟"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"ریکارڈ شدہ مواد محفوظ ہو جائے گا۔"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> کی ریکارڈنگ روک دی جائے گی کیونکہ یہ اس پروگرام کے ساتھ متضاد ہے۔ ریکارڈ کردہ مواد محفوظ ہو جائے گا۔"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"ریکارڈنگ کا شیڈول لیکن تضادات"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"ریکارڈنگ شروع ہو گئی ہے لیکن اس میں تضادات ہیں"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> ریکارڈ ہوجائے گا۔"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"اسی پروگرام کا پہلے ہی <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> بجے ریکارڈ ہونے کیلئے شیڈول بنا ہوا ہے۔"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"پہلے سے ریکارڈ شدہ"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"‏یہ پروگرام پہلے سے ہی ریکارڈ شدہ ہے۔ یہ DVR لائبریری میں دستیاب ہے۔"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"سیریز کی ریکارڈنگ کا شیڈول بن گیا ہے"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ریکارڈنگز کا شیڈول بن گیا ہے۔</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ریکارڈنگ کا شیڈول بن گیا ہے۔</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ریکارڈنگز کا شیڈول بن گیا ہے۔ تضادات کی وجہ سے ان میں سے <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> ریکارڈ نہیں ہوں گی۔</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ریکارڈنگ کا شیڈول بن گیا ہے۔ تضادات کی وجہ سے اس کی ریکارڈنگ نہیں ہو گی۔</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ریکارڈنگز کا شیڈول بن گیا ہے۔ تضادات کی وجہ سے اس سیریز اور دیگر سیریز کی <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> اقساط ریکارڈ نہیں ہوں گی۔</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ریکارڈنگ کا شیڈول بن گیا ہے۔ تضادات کی وجہ سے اس سیریز اور دیگر سیریز کی <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> اقساط ریکارڈ نہیں ہوں گی۔</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ریکارڈنگز کا شیڈول بن گیا ہے۔ تضادات کی وجہ سے دیگر سیریز کی 1 قسط ریکارڈ نہیں ہو گی۔</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ریکارڈنگ کا شیڈول بن گیا ہے۔ تضادات کی وجہ سے دیگر سیریز کی 1 قسط ریکارڈ نہیں ہو گی۔</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ریکارڈنگز کا شیڈول بن گیا ہے۔ تضادات کی وجہ سے دیگر سیریز کی <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> اقساط ریکارڈ نہیں ہوں گی۔</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> کیلئے <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ریکارڈنگ کا شیڈول بن گیا ہے۔ تضادات کی وجہ سے دیگر سیریز کی <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> اقساط ریکارڈ نہیں ہوں گی۔</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"ریکارڈ شدہ پروگرام نہیں ملا۔"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"متعلقہ ریکارڈنگز"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(پروگرام کی کوئی تفصیل نہیں)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">‏%1$d ریکارڈنگز</item>
       <item quantity="one">‏%1$d ریکارڈنگ</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"سیریز ریکارڈنگ روکیں؟"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"‏ریکارڈ شدہ ایپی سوڈز DVR لائبریری میں دستیاب رہیں گے۔"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"روکیں"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"ابھی کوئی ایپی سوڈ آن ائیر نہیں ہے۔"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"کوئی ایپی سوڈز دستیاب نہیں۔\nایک بار دستیاب ہوجائے تو ان کو ریکارڈ کیا جائے گا۔"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">‏(%1$d منٹ)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> آج"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> آئندہ کل"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"اسکور"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"ریکارڈ شدہ پروگرامز"</string>
 </resources>
diff --git a/res/values-uz-v23/strings.xml b/res/values-uz-rUZ-v23/strings.xml
similarity index 100%
rename from res/values-uz-v23/strings.xml
rename to res/values-uz-rUZ-v23/strings.xml
diff --git a/res/values-uz/arrays.xml b/res/values-uz-rUZ/arrays.xml
similarity index 100%
rename from res/values-uz/arrays.xml
rename to res/values-uz-rUZ/arrays.xml
diff --git a/res/values-uz/rating_system_strings.xml b/res/values-uz-rUZ/rating_system_strings.xml
similarity index 100%
rename from res/values-uz/rating_system_strings.xml
rename to res/values-uz-rUZ/rating_system_strings.xml
diff --git a/res/values-uz/strings.xml b/res/values-uz-rUZ/strings.xml
similarity index 78%
rename from res/values-uz/strings.xml
rename to res/values-uz-rUZ/strings.xml
index 55a0324..ff37421 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Boshqaruv"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"So‘nggi kanallar"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kanallar"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"TV sozlamalari"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP sozlamalari"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Ushbu kanal uchun ijro etish boshqaruvlari mavjud emas"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Ijro yoki pauza"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Oldinga tezkor o‘tkazish"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Taglavhalar"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Ekran rejimi"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"Kadr ustida kadr"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Yoniq"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"O‘chiq"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Ko‘p kanalli"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Boshqa kanallar"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Sozlamalar"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Manba"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Almashtirish"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Yoniq"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"O‘chiq"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Ovoz"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Asosiy oyna"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP oynasi"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Joylashuvi"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Pastda o‘ngda"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Tepada o‘ngda"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Tepada chapda"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Pastda chapda"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Yonma-yon"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"O‘lchami"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Katta"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Kichik"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Kirish manbasi"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (antenna/kabel)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Dastur haqida ma’l. yo‘q"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Ma’lumot yo‘q"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Bloklangan kanal"</string>
-    <string name="default_language" msgid="4122326459624337928">"Noma’lum til"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Noma’lum til"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Taglavhalar %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Taglavhalar"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"O‘chiq"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Formatlarni sozlash"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Guruhlash tartibi"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Bu dastur bloklangan"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Bu dastur tasniflanmagan"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Bu dastur uchun yosh cheklovi: <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Bu kirish avtomatik qidiruvni qo‘llab-quvvatlamaydi"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"“<xliff:g id="TV_INPUT">%s</xliff:g>” uchun avtomatik qidiruvni boshlab bo‘lmadi"</string>
@@ -92,12 +74,11 @@
       <item quantity="one">%1$d ta kanal qo‘shildi</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Kanal qo‘shilmadi"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Tyuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Ota-ona nazorati"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Yoniq"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"O‘chiq"</string>
     <string name="option_channels_locked" msgid="5797855082297549907">"Kanallar bloklandi"</string>
-    <string name="option_channels_lock_all" msgid="6594512884477342940">"Barchasini bloklash"</string>
+    <string name="option_channels_lock_all" msgid="6594512884477342940">"Hammasini bloklash"</string>
     <string name="option_channels_unlock_all" msgid="6839513296447567623">"Blokdan chiqarish"</string>
     <string name="option_channels_subheader_hidden" msgid="4669425935426972078">"Berkitilgan kanallar"</string>
     <string name="option_program_restrictions" msgid="241342023067364108">"Yosh cheklovlari"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Boshqa mamlakatlar"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Hech biri"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Hech biri"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Tasniflanmagan"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Tasniflanmagan dasturlarni bloklash"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Hech biri"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Qat’iy cheklovlar"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"O‘rtacha cheklovlar"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Bu kanalni ko‘rish uchun PIN kodni kiriting"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Bu dasturni ko‘rish uchun PIN kodni kiriting"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Bu dastur uchun yosh cheklovi: <xliff:g id="RATING">%1$s</xliff:g>. Bu dasturni ko‘rish uchun PIN kodni kiriting"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Bu dastur tasniflanmagan. Mazkur dasturni tomosha qilish uchun PIN kodni kiriting"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"PIN kodni kiriting"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Ota-ona nazoratini o‘rnatish uchun PIN-kod yarating"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Yangi PIN kodni kiriting"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN-kod noto‘g‘ri, qaytadan urining."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Qaytadan urinib ko‘ring, PIN-kod noto‘g‘ri"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Pochta indeksini kiriting."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Jonli efir ilovasi TV kanallari uchun to‘liq teledasturlarni taqdim etish uchun pochta indeksidan foydalanadi."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Pochta indeksini kiriting"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Pochta indeksi xato"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Sozlamalar"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Ro‘yxatni sozlash"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Teledastur uchun kanallarni tanlash"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Kanal manbalari"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Yangi kanallar topildi"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Ota-ona nazorati"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Tomosha qilayotganingizda yozib boring, bunda jonli dasturlarni pauzaga qo‘yishingiz  yoki orgaga qaytarishingiz mumkin bo‘ladi.\nDiqqat! Bu funksiyasi yoqilganda, ichki xotira intensiv ishlatiladi. Natijada uning xizmat muddati qisqarishi mumkin."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Ochiq kodli DT litsenziyalari"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Ochiq kodli DT litsenziyalari"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Fikr-mulohaza yuborish"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Versiyasi"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Bu kanalni ko‘rish uchun o‘ngga qaragan chiziqni bosing va PIN kodni kiriting"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Bu dasturni ko‘rish uchun o‘ngga qaragan chiziqni bosing va PIN kodni kiriting"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Bu dastur tasniflanmagan.\nMazkur dasturni tomosha qilish uchun o‘ngga strelkani bosing va PIN kodni kiriting"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Bu dastur uchun yosh cheklovi: <xliff:g id="RATING">%1$s</xliff:g>.\nUshbu dasturni ko‘rish uchun o‘ngga qaragan milni bosing va PIN-kodni kiriting."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Bu kanallarni ko‘rish uchun birlamchi “Jonli efir” ilovasidan foydalaning."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Bu dasturni ko‘rish uchun birlamchi “Jonli efir” ilovasidan foydalaning."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Bu dastur tasniflanmagan.\nMazkur dasturni tomosha qilish uchun birlamchi Jonli efir ilovasidan foydalaning."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Bu dastur uchun yosh cheklovi: <xliff:g id="RATING">%1$s</xliff:g>.\nUshbu dasturni ko‘rish uchun birlamchi “Jonli efir” ilovasidan foydalaning."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Dastur bloklangan"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Bu dastur tasniflanmagan"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Bu dastur uchun yosh cheklovi: <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Faqat audio"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Signal kuchsiz"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"TV menyusiga kirish uchun "<b>"TANLASH tugmasini bosing"</b>"."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Hech qanday TV-kirish topilmadi"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"TV-kirishni topib bo‘lmadi"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP qo‘llab-quvvatlanmaydi"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"PIP bilan ko‘rsatish uchun hech qanday manba yo‘q"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Tyuner turi mos kelmaydi. Agar TV-kirishdan foydalanayotgan bo‘lsangiz, “Jonli efir” ilovasini ishga tushiring."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Sozlashni amalga oshirib bo‘lmadi."</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Bu amalni bajara oladigan ilova topilmadi."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d ta yozuv rejalashtirilgan</item>
       <item quantity="one">%1$d ta yozuv rejalashtirilgan</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Yozib olishni bekor qilish"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Yozib olishni to‘xtatish"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Tomosha qilish"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Boshidan ijro etish"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Ijroni davom ettirish"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Bir vaqtning o‘zida bir nechta dasturlar yozib olinishi kerak bo‘lsa, faqat muhimlilik darajasi yuqori dasturlargina yozib olinadi."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Saqlash"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Bir martalik yozuvlarning muhimlilik darajasi yuqori"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Bekor q-sh"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Bekor qilish"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"O‘chirib tashlash"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"To‘xtatish"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Yozib olish jadvalini ko‘rish"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Faqat bu dastur"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Bu dasturni yozib olish"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Bu yozib olishni bekor qilish"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Tomosha qilish"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Yozuvlarni o‘chirish…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Yozib olish mumkin"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Yozib olish rejalashtirildi"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Yozib olish taymerida ziddiyat"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Yozib olish"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Yozib olib bo‘lmadi"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Yozib olish jadvallarini yaratish uchun dasturlar o‘qib chiqilmoqda"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Dasturlar o‘qib chiqilmoqda"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Dasturlar o‘qib chiqilmoqda"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Oxirgi yozuvlarni ko‘rish"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"“<xliff:g id="PROGRAMNAME">%1$s</xliff:g>” to‘liq yozib olinmadi."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"“<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>” va “<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>” to‘liq yozib olinmadi."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"“<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>”, “<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>” va “<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>” to‘liq yozib olinmadi."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Xotirada joy kamligi tufayli “<xliff:g id="PROGRAMNAME">%1$s</xliff:g>” to‘liq yozib olinmadi."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Xotirada joy kamligi tufayli “<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>” va “<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>” to‘liq yozib olinmadi."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Xotirada joy kamligi tufayli “<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>”, “<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>” va “<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>” to‘liq yozib olinmadi."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR uchun ko‘proq joy kerak"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Dasturlarni DVR orqali yozib olish mumkin. Lekin hozir DVR ishlashi uchun qurilmangizda yetarli joy qolmadi. <xliff:g id="STORAGE_SIZE">%1$s</xliff:g> GB va undan katta hajmli tashqi xotira qurilmasini ulang va qurilma xotirasi sifatida formatlash uchun ko‘rsatmalarga amal qiling."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Dasturlarni DVR orqali yozib olish mumkin. Lekin hozir DVR ishlashi uchun qurilmangizda yetarli joy qolmadi. <xliff:g id="STORAGE_SIZE">%1$d</xliff:g> GB va undan katta hajmli tashqi xotira qurilmasini ulang va qurilma xotirasi sifatida formatlash uchun ko‘rsatmalarga amal qiling."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Xotirada joy yetarli emas"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Joy yetarli bo‘lmagani uchun bu dasturni yozib bo‘lmaydi. Eski yozuvlarni bir nechtasini o‘chirib tashlab ko‘ring."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Xotira mavjud emas"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Xotira topilmadi. Videomagnitofonni qayta yoqishdan oldin tashqi xotirani ulang yoki undan foydalanib bo‘lmasa, xotirani o‘chirib tashlang."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Xotira o‘chirib tashlansinmi?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Barcha yozib olingan kontentlar va jadvallar o‘chib ketadi."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Yozib olish to‘xtatilsinmi?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Yozib olingan kontent saqlab qo‘yiladi."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Bu dastur bilan ixtilof borligi uchun “<xliff:g id="PROGRAMNAME">%1$s</xliff:g>” dasturini yozib olish to‘xtatiladi. Yozib olingan qismi saqlab olinadi."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Yozib olish rejalashtirildi, lekin ixtiloflar bor"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Yozib olish jadvalida ixtiloflar bor"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"“<xliff:g id="PROGRAMNAME">%1$s</xliff:g>” dasturi yozib olinadi."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Bu dasturni allaqachon <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> da yozib olish rejalashtirilgan."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Dastur allaqachon yozib olingan"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Bu dastur allaqachon yozib olingan. U DVR kutubxonasida saqlanadi."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Seriallarni yozib olish rejalashtirildi"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ta yozuv rejalashtirilgan.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ta yozuv rejalashtirilgan.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ta yozuv rejalashtirilgan. Ixtiloflar borligi uchun ulardan <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> tasi yozib olinmaydi.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ta yozuv rejalashtirilgan. Ixtiloflar borligi uchun u yozib olinmaydi.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ta yozuv rejalashtirilgan. Ixtiloflar borligi uchun bu serialning <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ta qismi va boshqa seriallar yozib olinmaydi.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ta yozuv rejalashtirilgan. Ixtiloflar borligi uchun bu serialning <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ta qismi va boshqa seriallar yozib olinmaydi.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="SERIESNAME_3">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ta yozuv rejalashtirilgan. Ixtiloflar borligi uchun boshqa seriallarning 1 ta qismi yozib olinmaydi.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ta yozuv rejalashtirilgan. Ixtiloflar borligi uchun boshqa seriallarning 1 ta qismi yozib olinmaydi.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="SERIESNAME_4">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ta yozuv rejalashtirilgan. Ixtiloflar borligi uchun boshqa seriallarning <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> ta qismi yozib olinmaydi.</item>
+      <item quantity="one"><xliff:g id="SERIESNAME_1">%2$s</xliff:g> uchun <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> ta yozuv rejalashtirilgan. Ixtiloflar borligi uchun boshqa seriallarning <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> ta qismi yozib olinmaydi.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Yozib olingan dasturni topib bo‘lmadi."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Aloqador yozuvlar"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Dastur haqida ma’lumot yo‘q)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d ta yozuv</item>
       <item quantity="one">%1$d ta yozuv</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Yozib olish to‘xtatilsinmi?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Yozib olingan qismlar DVR kutubxonasida saqlanadi."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"To‘xtatish"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Hozir hech qaysi serial qismi efirga uzatilmayapti."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Hali serial qismi chiqmagan.\nEfirga chiqishi bilan yozib olinadi."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d daqiqa)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"Bugun <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"Ertaga <xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Ball"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Yozib olingan dasturlar"</string>
 </resources>
diff --git a/res/values-v23/strings.xml b/res/values-v23/strings.xml
deleted file mode 100644
index 4809682..0000000
--- a/res/values-v23/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Title of the channels row in the main menu. [CHAR LIMIT=NONE] -->
-    <string name="menu_title_channels">Channels</string>
-</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index a8c4ab0..a1aae94 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"đơn âm"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"âm thanh nổi"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Điều khiển phát"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Kênh gần đây"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Kênh"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Tùy chọn TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Tùy chọn PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Điều khiển phát không có sẵn cho kênh này"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Phát hoặc tạm dừng"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Tua đi"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Phụ đề"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Chế độ hiển thị"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Bật"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Tắt"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Âm thanh đa kênh"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Tải thêm kênh"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Cài đặt"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Nguồn"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Hoán đổi"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Bật"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Tắt"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Âm thanh"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Cửa sổ chính"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Cửa sổ PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Bố cục"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Phía dưới cùng bên phải"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Phía trên cùng bên phải"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Phía trên cùng bên trái"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Phía dưới cùng bên trái"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"Cạnh nhau"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Kích thước"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Lớn"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Nhỏ"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Nguồn đầu vào"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"TV (ăng-ten/cáp)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Không có thông tin chương trình"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Không có thông tin"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Kênh bị chặn"</string>
-    <string name="default_language" msgid="4122326459624337928">"Tiếng không xác định"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Ngôn ngữ không xác định"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Phụ đề chi tiết %1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Phụ đề"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Tắt"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Tùy chỉnh định dạng"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Nhóm theo"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Chương trình này đã bị chặn"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Chương trình này chưa được xếp hạng"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Chương trình này được xếp hạng <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Đầu vào không hỗ trợ tự động quét"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Không thể bắt đầu quét tự động cho \'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">Đã thêm %1$d kênh</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Chưa thêm kênh nào"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"Bộ dò"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Kiểm soát của cha mẹ"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Bật"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Tắt"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Các quốc gia khác"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Không có"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Không có"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Chưa được xếp hạng"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Chặn chương trình chưa có hạng"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Không có"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Hạn chế cao"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Hạn chế trung bình"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Nhập mã PIN của bạn để xem kênh này"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Nhập mã PIN của bạn để xem chương trình này"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Chương trình này được xếp hạng <xliff:g id="RATING">%1$s</xliff:g>. Nhập mã PIN của bạn để xem chương trình này"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Chương trình này chưa được xếp hạng. Hãy nhập mã PIN của bạn để xem chương trình này"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Nhập mã PIN của bạn"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Để đặt kiểm soát của phụ huynh, hãy tạo mã PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Nhập mã PIN mới"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Mã PIN đó không đúng. Hãy thử lại."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Hãy thử lại, mã PIN không khớp"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Nhập mã ZIP của bạn."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Ứng dụng Kênh trực tiếp sẽ sử dụng mã ZIP để cung cấp hướng dẫn chương trình đầy đủ cho các kênh truyền hình."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Nhập mã ZIP của bạn"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Mã ZIP không hợp lệ"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Cài đặt"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Tùy chỉnh danh sách kênh"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Chọn kênh cho hướng dẫn chương trình của bạn"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Nguồn kênh"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Đã có kênh mới"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Kiểm soát của phụ huynh"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"Chuyển dịch thời gian"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Ghi lại trong khi xem để bạn có thể tạm dừng hoặc tua lại các chương trình trực tiếp.\nCảnh báo: Điều này có thể làm giảm tuổi thọ của bộ nhớ trong bằng cách sử dụng nhiều bộ nhớ."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Giấy phép nguồn mở"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Giấy phép nguồn mở"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Gửi phản hồi"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Phiên bản"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Để xem kênh này, hãy nhấn vào Quyền và nhập mã PIN của bạn"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Để xem chương trình này, hãy nhấn vào Quyền và nhập mã PIN của bạn"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Chương trình này chưa được xếp hạng.\nĐể xem chương trình này, hãy nhấn vào phím Phải và nhập mã PIN của bạn"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Chương trình này được xếp hạng <xliff:g id="RATING">%1$s</xliff:g>.\nĐể xem chương trình này, hãy nhấn vào Quyền và nhập mã PIN của bạn."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Để xem kênh này, hãy sử dụng ứng dụng Truyền hình trực tiếp mặc định."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Để xem chương trình này, hãy sử dụng ứng dụng Truyền hình trực tiếp mặc định."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Chương trình này chưa được xếp hạng.\nĐể xem chương trình này, hãy sử dụng ứng dụng Truyền hình trực tiếp mặc định."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Chương trình này được xếp hạng <xliff:g id="RATING">%1$s</xliff:g>.\nĐể xem chương trình này, hãy sử dụng ứng dụng Truyền hình trực tiếp mặc định."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Chương trình bị chặn"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Chương trình này chưa được xếp hạng"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Chương trình này được xếp hạng <xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Chỉ âm thanh"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Tín hiệu yếu"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Nhấn CHỌN"</b>" để truy cập menu TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Không tìm thấy đầu vào TV nào"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Không tìm thấy đầu vào TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP không được hỗ trợ"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Không có đầu vào có thể hiển thị với PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"Loại bộ dò ko phù hợp. Hãy chạy ứng dụng Kênh trực tiếp cho đầu vào TV loại bộ dò."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Không dò được"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Không tìm thấy ứng dụng nào để xử lý tác vụ này."</string>
@@ -226,6 +217,8 @@
       <item quantity="other">%1$d bản ghi được lên lịch</item>
       <item quantity="one">%1$d bản ghi được lên lịch</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Hủy ghi"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Dừng ghi"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Xem"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Phát từ đầu"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Tiếp tục phát"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Khi có quá nhiều chương trình được ghi cùng lúc, chỉ có những chương trình với mức ưu tiên cao hơn sẽ được ghi."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Lưu"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Ghi một lần có mức độ ưu tiên cao nhất"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Hủy"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Hủy"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Quên"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Dừng"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Xem lịch ghi"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Chương trình duy nhất này"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Ghi chương trình này để thay thế"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Hủy lịch ghi này"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Xem ngay bây giờ"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Xóa bản ghi…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Có thể ghi được"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Đã lên lịch ghi"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Lịch ghi xung đột"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Đang ghi"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Ghi không thành công"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Đang đọc các chương trình để tạo lịch ghi"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Đang đọc chương trình"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Đang đọc chương trình"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Xem bản ghi gần đây"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Quá trình ghi <xliff:g id="PROGRAMNAME">%1$s</xliff:g> không hoàn thành."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Quá trình ghi <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> và <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> không hoàn thành."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Quá trình ghi <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> và <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> không hoàn thành."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Quá trình ghi <xliff:g id="PROGRAMNAME">%1$s</xliff:g> đã không hoàn thành do không đủ bộ nhớ."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Quá trình ghi <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> và <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> đã không hoàn thành do không đủ bộ nhớ."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Quá trình ghi <xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> và <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> đã không hoàn thành do không đủ bộ nhớ."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR cần thêm bộ nhớ"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Bạn sẽ có thể ghi các chương trình với DVR. Tuy nhiên không có đủ bộ nhớ trên thiết bị của bạn bây giờ để DVR hoạt động. Vui lòng kết nối ổ đĩa ngoài <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB hoặc lớn hơn và làm theo các bước để định dạng ổ đĩa ngoài làm thiết bị lưu trữ."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Bạn sẽ có thể ghi các chương trình với DVR. Tuy nhiên không có đủ bộ nhớ trên thiết bị của bạn bây giờ để DVR hoạt động. Vui lòng kết nối ổ đĩa ngoài <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB hoặc lớn hơn và làm theo các bước để định dạng ổ đĩa ngoài làm thiết bị lưu trữ."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Không đủ bộ nhớ"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Chương trình này sẽ không được ghi vì không có đủ bộ nhớ. Hãy thử xóa một số bản ghi hiện có."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Thiếu bộ nhớ"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Một số bộ nhớ được DVR sử dụng bị thiếu. Vui lòng kết nối các ổ đĩa ngoài bạn đã sử dụng trước đó để bật lại DVR. Ngoài ra bạn còn có thể chọn để quên bộ nhớ nếu bộ nhớ không còn nữa."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Quên bộ nhớ?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Tất cả nội dung đã ghi và lịch ghi của bạn sẽ bị mất."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Dừng ghi?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Nội dung đã ghi sẽ được lưu."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Quá trình ghi <xliff:g id="PROGRAMNAME">%1$s</xliff:g> sẽ bị dừng lại vì mâu thuẫn với chương trình này. Nội dung đã ghi sẽ được lưu."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Đã lên lịch ghi nhưng có xung đột"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Đã bắt đầu ghi nhưng có xung đột"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> sẽ được ghi."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Chương trình tương tự đã được lên lịch để ghi lúc <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Đã được ghi"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Chương trình này đã được ghi. Chương trình có sẵn trong thư viện DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Đã lên lịch ghi loạt phim"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_1">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> trong số chúng sẽ không được ghi do xung đột.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. Bản ghi sẽ không được ghi do xung đột.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> tập của loạt phim này và các loạt phim khác sẽ không được ghi do xung đột.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> tập của loạt phim này và các loạt phim khác sẽ không được ghi do xung đột.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 tập của loạt phim khác sẽ không được ghi do xung đột.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. 1 tập của loạt phim khác sẽ không được ghi do xung đột.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> tập của loạt phim khác sẽ không được ghi do xung đột.</item>
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> bản ghi đã được lên lịch cho <xliff:g id="SERIESNAME_1">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> tập của loạt phim khác sẽ không được ghi do xung đột.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Không tìm thấy chương trình nào được ghi."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Bản ghi liên quan"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Không có mô tả chương trình)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d bản ghi</item>
       <item quantity="one">%1$d bản ghi</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Dừng ghi loạt phim?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Các tập đã ghi sẽ vẫn có sẵn trong thư viện DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Dừng"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Không có tập nào đang chiếu bây giờ."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Không có sẵn tập nào.\nChúng sẽ được ghi khi có sẵn."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d phút)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> hôm nay"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> ngày mai"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Điểm"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Chương trình đã ghi"</string>
 </resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index e3d8ea0..2aa3e2c 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"单声道"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"立体声"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"播放控件"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"最近观看的频道"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"频道"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"电视选项"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP 选项"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"此频道无法使用播放控件"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"播放或暂停"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"快进"</string>
@@ -34,34 +33,16 @@
     <string name="channels_item_app_link_app_launcher" msgid="1395352122187670523">"打开<xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="options_item_closed_caption" msgid="5945274655046367170">"字幕"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"显示模式"</string>
-    <string name="options_item_pip" msgid="3951350386626879645">"PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"开启"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"关闭"</string>
+    <string name="options_item_pip" msgid="3951350386626879645">"画中画"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"多音频"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"获取更多频道"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"设置"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"来源"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"切换"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"开启"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"关闭"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"声音"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"主窗口"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"PIP 窗口"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"布局"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"右下方"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"右上方"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"左上方"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"左下方"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"并排"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"尺寸"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"大"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"小"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"输入源"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"电视(天线/有线)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"没有节目信息"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"无信息"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"已屏蔽的频道"</string>
-    <string name="default_language" msgid="4122326459624337928">"未知语言"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"未知语言"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"字幕(%1$d)"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"字幕"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"关闭"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"自定义格式"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"标清"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"分组依据"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"此节目已被屏蔽"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"此节目未分级"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"此节目的分级为:<xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"该输入设备不支持自动扫描"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"无法为“<xliff:g id="TV_INPUT">%s</xliff:g>”启动自动扫描"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">已添加 %1$d 个频道</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"未添加任何频道"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"调谐器"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"家长控制"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"开启"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"关闭"</string>
@@ -101,13 +82,15 @@
     <string name="option_channels_unlock_all" msgid="6839513296447567623">"全部取消屏蔽"</string>
     <string name="option_channels_subheader_hidden" msgid="4669425935426972078">"隐藏的频道"</string>
     <string name="option_program_restrictions" msgid="241342023067364108">"节目限制"</string>
-    <string name="option_change_pin" msgid="2881594075631152566">"更改PIN码"</string>
+    <string name="option_change_pin" msgid="2881594075631152566">"更改 PIN 码"</string>
     <string name="option_country_rating_systems" msgid="7288569813945260224">"分级系统"</string>
     <string name="option_ratings" msgid="4009116954188688616">"分级"</string>
     <string name="option_see_all_rating_systems" msgid="7702673500014877288">"查看所有分级系统"</string>
     <string name="other_countries" msgid="8342216398676184749">"其他国家/地区"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"无"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"无"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"未分级"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"屏蔽未分级的节目"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"无"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"严格限制"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"中等限制"</string>
@@ -121,36 +104,46 @@
     <skip />
     <string name="option_subrating_title" msgid="5485055507818077595">"%1$s和二级分级"</string>
     <string name="option_subrating_header" msgid="4637961301549615855">"二级分级"</string>
-    <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"输入PIN码即可观看此频道"</string>
-    <string name="pin_enter_unlock_program" msgid="7311628843209871203">"输入PIN码即可观看此节目"</string>
+    <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"输入 PIN 码即可观看此频道"</string>
+    <string name="pin_enter_unlock_program" msgid="7311628843209871203">"输入 PIN 码即可观看此节目"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"该节目的分级是“<xliff:g id="RATING">%1$s</xliff:g>”。要观看此节目,请输入您的 PIN 码"</string>
-    <string name="pin_enter_pin" msgid="249314665028035038">"输入您的PIN码"</string>
-    <string name="pin_enter_create_pin" msgid="3385754356793309946">"要设置家长控制功能,请创建一个PIN码"</string>
-    <string name="pin_enter_new_pin" msgid="1739471585849790384">"请输入新的PIN码"</string>
-    <string name="pin_enter_again" msgid="2618999754723090427">"确认您的PIN码"</string>
-    <string name="pin_enter_old_pin" msgid="4588282612931041919">"输入当前的PIN码"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"此节目未分级。要观看此节目,请输入您的 PIN 码"</string>
+    <string name="pin_enter_pin" msgid="249314665028035038">"输入您的 PIN 码"</string>
+    <string name="pin_enter_create_pin" msgid="3385754356793309946">"要设置家长控制功能,请创建一个 PIN 码"</string>
+    <string name="pin_enter_new_pin" msgid="1739471585849790384">"请输入新的 PIN 码"</string>
+    <string name="pin_enter_again" msgid="2618999754723090427">"确认您的 PIN 码"</string>
+    <string name="pin_enter_old_pin" msgid="4588282612931041919">"输入当前的 PIN 码"</string>
     <plurals name="pin_enter_countdown" formatted="false" msgid="3415233538538544309">
       <item quantity="other">您已连续 5 次输错 PIN 码。\n请在 <xliff:g id="REMAINING_SECONDS_1">%1$d</xliff:g> 秒后重试。</item>
       <item quantity="one">您已连续 5 次输错 PIN 码。\n请在 <xliff:g id="REMAINING_SECONDS_0">%1$d</xliff:g> 秒后重试。</item>
     </plurals>
-    <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN码不正确,请重试。"</string>
-    <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN码不匹配,请重试"</string>
+    <string name="pin_toast_wrong" msgid="2126295626095048746">"PIN 码不正确,请重试。"</string>
+    <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN 码不匹配,请重试"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"请输入您的邮政编码。"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"直播频道应用将使用邮政编码提供完整的电视频道收视指南。"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"请输入您的邮政编码"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"邮政编码无效"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"设置"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"自定义频道列表"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"为您的收视指南选择频道"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"频道来源"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"有新频道"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"家长控制"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"时移"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"一边观看一边录制,这样您就能够让直播节目暂停或快退。\n警告:此功能会密集占用存储空间,因此可能会缩短内部存储空间的使用寿命。"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"开放源代码许可"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"开放源代码许可"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"发送反馈"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"版本"</string>
-    <string name="tvview_channel_locked" msgid="6486375335718400728">"要观看此频道,请按“向右”按钮,然后输入您的PIN码"</string>
-    <string name="tvview_content_locked" msgid="391823084917017730">"要观看此节目,请按“向右”按钮,然后输入您的PIN码"</string>
+    <string name="tvview_channel_locked" msgid="6486375335718400728">"要观看此频道,请按“向右”按钮,然后输入您的 PIN 码"</string>
+    <string name="tvview_content_locked" msgid="391823084917017730">"要观看此节目,请按“向右”按钮,然后输入您的 PIN 码"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"此节目未分级。\n要观看此节目,请按向右键并输入您的 PIN 码"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"此节目的分级为:<xliff:g id="RATING">%1$s</xliff:g>。\n要观看此节目,请按“向右”按钮,然后输入您的 PIN 码。"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"要观看此频道,请使用默认的“电视直播”应用。"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"要观看此节目,请使用默认的“电视直播”应用。"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"此节目未分级。\n要观看此节目,请使用默认的“电视直播”应用。"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"该节目的分级是“<xliff:g id="RATING">%1$s</xliff:g>”。\n要观看此节目,请使用默认的“电视直播”应用。"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"节目已被屏蔽"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"此节目未分级"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"此节目的分级为:<xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"仅提供音频"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"信号弱"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"按“选择”"</b>"可访问电视菜单。"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"未检测到电视输入设备"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"找不到该电视输入设备"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"不支持 PIP"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"没有可通过 PIP 方式显示的输入"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"不支持调谐器类型。请启动支持调谐器类型电视输入端口的“直播频道”应用。"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"调谐失败"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"未找到可处理此操作的应用。"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">已安排录制 %1$d 项内容</item>
       <item quantity="one">已安排录制 %1$d 项内容</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"取消录制"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"停止录制"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"观看"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"从头播放"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"继续播放"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"如果同一时段有太多的节目要录制,系统只会录制优先级较高的节目。"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"保存"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"一次性录制内容具有最高优先级"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"取消"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"取消"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"移除"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"停止"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"查看录制时间表"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"只录这一集节目"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"改录这个节目"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"取消这项录制安排"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"立即观看"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"删除录制的节目…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"可录制"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"已排定录制时间"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"录制冲突"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"正在录制"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"录制失败"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"正在读取节目以创建录制时间安排表"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"正在读取节目"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"正在读取节目"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"查看最近的录制内容"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g>的录制没有完成。"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>和<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>的录制没有完成。"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>、<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>和<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>的录制没有完成。"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"由于存储空间不足,<xliff:g id="PROGRAMNAME">%1$s</xliff:g>的录制没有完成。"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"由于存储空间不足,<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>和<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>的录制没有完成。"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"由于存储空间不足,<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>、<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>和<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>的录制没有完成。"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR 需要更多存储空间"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"您将可以使用 DVR 录制节目,但目前您设备上的存储空间不足,因此无法使用 DVR。请连接存储空间不小于 <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB 的外部驱动器,然后按照相关步骤将其格式化为设备的存储空间。"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"您将可以使用 DVR 录制节目,但目前您设备上的存储空间不足,因此无法使用 DVR。请连接存储空间不小于 <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB 的外部驱动器,然后按照相关步骤将其格式化为设备的存储空间。"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"存储空间不足"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"由于存储空间不足,系统将不会录制此节目。请尝试删除部分已录制的节目。"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"无法访问存储空间"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"无法访问 DVR 使用的部分存储空间。请连接您先前使用的外部驱动器,以重新启用 DVR。如果存储空间已无法再使用,您也可以选择忽略该存储空间。"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"要移除此存储空间吗?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"您的所有录制内容和录制安排计划都将丢失。"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"要停止录制吗?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"系统将保存已录制的内容。"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"系统将停止录制《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》,因为它与此节目存在冲突。系统将保存已录制的内容。"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"已排定录制时间,但录制时间存在冲突"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"已开始录制,但存在冲突"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"系统将会录制《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》。"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"已安排在以下时间录制同一节目:<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>。"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"已录制"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"此节目已完成录制并保存在 DVR 媒体库中。"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"已排定剧集录制时间"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">已为《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 项录制计划。</item>
+      <item quantity="one">已为《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 项录制计划。</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">已为《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 项录制计划。由于存在冲突,系统将无法录制其中 <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> 集节目。</item>
+      <item quantity="one">已为《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 项录制计划。由于存在冲突,系统将无法录制这集节目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">已为《<xliff:g id="SERIESNAME_4">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> 项录制计划。由于存在冲突,系统将无法录制此剧集和其他剧集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> 集节目。</item>
+      <item quantity="one">已为《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 项录制计划。由于存在冲突,系统将无法录制此剧集和其他剧集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> 集节目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">已为《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 项录制计划。由于存在冲突,系统将无法录制其他剧集的 1 集节目。</item>
+      <item quantity="one">已为《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 项录制计划。由于存在冲突,系统将无法录制其他剧集的 1 集节目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">已为《<xliff:g id="SERIESNAME_4">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> 项录制计划。由于存在冲突,系统将无法录制其他剧集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> 集节目。</item>
+      <item quantity="one">已为《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 项录制计划。由于存在冲突,系统将无法录制其他剧集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> 集节目。</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"未找到录制的节目。"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"相关录制内容"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(没有节目说明)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d 项录制内容</item>
       <item quantity="one">%1$d 项录制内容</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"要停止创建剧集录制时间表吗?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"已录制的剧集仍会保存到 DVR 媒体库中。"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"停止"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"目前没有任何正在播出的剧集。"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"没有已录制的剧集。\n一旦有剧集可供录制,系统将立即开始录制。"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d 分钟)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"今天<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"明天<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"评分"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"已录制的节目"</string>
 </resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 5fe984d..05e0b9e 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"單聲道"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"立體聲"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"播放控制"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"最近觀看的頻道"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"頻道"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"電視選項"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"PIP 選項"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"播放控制功能不適用於此頻道"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"播放或暫停"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"向前快轉"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"隱藏式字幕"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"顯示模式"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"子母畫面"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"開啟"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"關閉"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"多聲道"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"取得更多頻道"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"設定"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"來源"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"切換"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"開啟"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"關閉"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"音效"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"主視窗"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"子母畫面視窗"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"版面配置"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"右下方"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"右上方"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"左上方"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"左下方"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"並排"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"大小"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"大"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"小"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"輸入源"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"電視 (天線/連接線)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"沒有節目資訊"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"無資訊"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"已封鎖的頻道"</string>
-    <string name="default_language" msgid="4122326459624337928">"不明語言"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"不明語言"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"隱藏式字幕 (%1$d)"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"隱藏式字幕"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"關閉"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"自訂格式"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"標清"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"分組依據"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"這個節目已被封鎖。"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"此節目未分級"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"這個節目的評級為<xliff:g id="RATING">%1$s</xliff:g>。"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"輸入裝置不支援自動掃瞄功能"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"無法啟動「<xliff:g id="TV_INPUT">%s</xliff:g>」的自動掃瞄"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">已新增 %1$d 個頻道</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"尚未新增任何頻道"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"調校器"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"家長監護"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"開啟"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"關閉"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"其他國家/地區"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"無"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"無"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"未分級"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"封鎖未分級的節目"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"無"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"嚴格限制"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"中等限制"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"輸入您的 PIN 即可觀看這個頻道"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"輸入您的 PIN 即可觀看這個節目"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"此節目的內容分級是「<xliff:g id="RATING">%1$s</xliff:g>」。如要觀看此節目,請輸入 PIN"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"此節目未分級。如要觀看此節目,請輸入您的 PIN"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"請輸入您的 PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"如要設定家長監護,請建立 PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"輸入新的 PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"該 PIN 錯誤,請再試一次。"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN 碼不符,請再試一次"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"請輸入郵遞區號。"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"「直播頻道」應用程式會利用郵遞區號,提供電視頻道的完整電視節目指南。"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"請輸入郵遞區號"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"郵遞區號無效"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"設定"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"自訂頻道清單"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"選擇頻道以建立電視節目指南"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"頻道來源"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"可供設定的新頻道"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"家長監控設定"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"時光平移"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"錄影正在觀看的直播節目,以便暫停播放節目或倒帶。\n警告:此功能會佔用大量儲存空間,因此可能會縮短內部儲存空間的使用壽命。"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"開放原始碼授權"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"開放原始碼授權"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"傳送意見"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"版本"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"按向右鍵並輸入您的 PIN,以觀看這個頻道"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"按向右鍵並輸入您的 PIN,以觀看這個節目"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"此節目未分級。\n如要觀看此節目,請按向右鍵並輸入您的 PIN"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"這個節目的評級為<xliff:g id="RATING">%1$s</xliff:g>。\n要觀看這個節目,請按向右鍵並輸入您的 PIN。"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"如要觀看此頻道,請使用預設電視直播應用程式。"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"如要觀看此節目,請使用預設電視直播應用程式。"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"此節目未分級。\n如要觀看此節目,請使用預設的「直播電視」應用程式。"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"此節目評級為「<xliff:g id="RATING">%1$s</xliff:g>」。\n如要觀看此節目,請使用預設電視直播應用程式。"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"節目被封鎖"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"此節目未分級"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"這個節目的評級為<xliff:g id="RATING">%1$s</xliff:g>。"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"只限音效"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"訊號微弱"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"按 [選擇]"</b>" 前往 [電視選單]。"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"找不到電視輸入"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"找不到電視輸入"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"PIP 不受支援"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"沒有可供 PIP 顯示的輸入"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"調諧器類型不適用;請啟動調諧器類型電視輸入專用的「直播頻道」應用程式。"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"調校失敗"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"找不到可以處理這項操作的應用程式。"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">已預定 %1$d 個錄影</item>
       <item quantity="one">已預定 %1$d 個錄影</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"取消錄影"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"停止錄影"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"觀看"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"從頭開始播放"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"恢復播放"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"如果同一時間有太多需要錄影的節目,系統只會錄影優先級別較高的節目。"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"儲存"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"單次錄影享有最高優先級別"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"取消"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"取消"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"刪除"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"停止"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"查看錄影時間表"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"只錄影這一集"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"改為錄影此節目"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"取消此錄影"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"立即觀看"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"刪除錄影節目…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"可錄影"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"已排定錄影時間"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"錄影時間有衝突"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"正在錄影"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"錄影失敗"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"正在讀取節目以建立錄影時間表"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"正在讀取節目"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"正在讀取節目"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"查看最近的錄影"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》未完成錄影。"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"《<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>》和《<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>》未完成錄影。"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"《<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>》、《<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>》和《<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>》未完成錄影。"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"由於儲存空間不足,因此《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》未完成錄影。"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"由於儲存空間不足,因此《<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>》和《<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>》未完成錄影。"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"由於儲存空間不足,因此《<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>》、《<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>》和《<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>》未完成錄影。"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR 需要更多儲存空間"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"您可以使用 DVR 錄影節目,但裝置目前的儲存空間不足,因此無法使用 DVR。請連接 <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB 或以上的外置硬碟,然後按步驟格式化,以用作裝置儲存空間。"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"您可以使用 DVR 錄影節目,但裝置目前的儲存空間不足,因此無法使用 DVR。請連接 <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB 或以上的外置硬碟,然後按步驟格式化,以用作裝置儲存空間。"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"儲存空間不足"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"由於儲存空間不足,因此無法錄影此節目。請嘗試刪除部分現有的錄影節目。"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"無法存取儲存空間"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"系統存取部分 DVR 使用的儲存空間。請連接您先前使用的外置磁碟,然後重新啟用 DVR。如果儲存空間已無法使用,您亦可選擇刪除儲存空間。"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"要刪除儲存空間嗎?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"所有已錄影的內容和時間表將會遺失。"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"要停止錄影嗎?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"系統將儲存已錄影的內容。"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"由於《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》的錄影時間與此節目有衝突,因此系統將停止錄影並儲存已錄影的內容。"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"已預定錄影時間,但與錄影時間有衝突"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"已開始錄影,但與其他預定錄影時間有衝突"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"系統將錄影《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》。"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"已預定在 <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>錄影相同的節目。"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"已錄影"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"系統已錄影此節目並儲存在 DVR 媒體庫中。"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"已預定劇集錄影時間"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 個錄影時間。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 個錄影時間。由於發生衝突,因此系統將不會錄影其中 <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> 集節目。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。由於發生衝突,因此系統將不會錄影該節目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_4">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> 個錄影時間。由於發生衝突,因此系統將不會錄影此劇集和其他劇集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> 集節目。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。由於發生衝突,因此系統將不會錄影此劇集和其他劇集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> 集節目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 個錄影時間。由於發生衝突,因此系統將不會錄影其他劇集的 1 集節目。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。由於發生衝突,因此系統將不會錄影其他劇集的 1 集節目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_4">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> 個錄影時間。由於發生衝突,因此系統將不會錄影其他劇集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> 集節目。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》預定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。由於發生衝突,因此系統將不會錄影其他劇集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> 集節目。</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"找不到已錄影的節目。"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"相關錄影"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(沒有節目說明)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d 個錄影</item>
       <item quantity="one">%1$d 個錄影</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"要停止錄影劇集嗎?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"已錄影的劇集仍將保留在 DVR 媒體庫中。"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"停止"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"目前沒有任何正在播出的劇集。"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"沒有可供錄影的劇集。\n系統會在劇集播出時立即錄影。"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d 分鐘)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"今天<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"明天<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"分數"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"已錄影的節目"</string>
 </resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index e33998b..d40ecb0 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"單聲道"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"立體聲"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"播放控制介面"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"最近觀看的頻道"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"頻道"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"電視選項"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"子母畫面選項"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"這個頻道無法使用播放控制介面"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"播放或暫停"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"快轉"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"字幕"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"顯示模式"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"子母畫面"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"開啟"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"關閉"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"多聲道"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"取得更多頻道"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"設定"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"來源"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"切換"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"開啟"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"關閉"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"音效"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"主視窗"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"子母畫面視窗"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"版面配置"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"右下角"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"右上角"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"左上角"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"左下角"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"並排"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"尺寸"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"大"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"小"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"輸入來源"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"電視 (有線/無線)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"沒有節目資訊"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"無資訊"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"封鎖的頻道"</string>
-    <string name="default_language" msgid="4122326459624337928">"不明語言"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"不明語言"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"隱藏式輔助字幕 (%1$d)"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"字幕"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"關閉"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"自訂格式設定"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"SD 標準畫質"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"分組依據"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"這個節目遭到封鎖"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"這個節目未分級"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"這個節目的分級是「<xliff:g id="RATING">%1$s</xliff:g>」。"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"輸入裝置不支援自動掃描"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"無法開始「<xliff:g id="TV_INPUT">%s</xliff:g>」的自動掃描作業"</string>
@@ -92,7 +74,6 @@
       <item quantity="one">新增了 %1$d 個頻道</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"尚未新增任何頻道"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"協調器"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"家長監護"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"開啟"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"關閉"</string>
@@ -101,13 +82,15 @@
     <string name="option_channels_unlock_all" msgid="6839513296447567623">"全部解除封鎖"</string>
     <string name="option_channels_subheader_hidden" msgid="4669425935426972078">"隱藏的頻道"</string>
     <string name="option_program_restrictions" msgid="241342023067364108">"節目限制"</string>
-    <string name="option_change_pin" msgid="2881594075631152566">"變更 PIN"</string>
+    <string name="option_change_pin" msgid="2881594075631152566">"變更 PIN 碼"</string>
     <string name="option_country_rating_systems" msgid="7288569813945260224">"分級系統"</string>
     <string name="option_ratings" msgid="4009116954188688616">"分級"</string>
     <string name="option_see_all_rating_systems" msgid="7702673500014877288">"查看所有分級制度"</string>
     <string name="other_countries" msgid="8342216398676184749">"其他國家/地區"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"無"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"無"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"未分級"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"封鎖未分級的節目"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"無"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"高度限制"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"中度限制"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"輸入您的 PIN 即可觀看這個頻道"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"輸入您的 PIN 即可觀看這個節目"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"這個節目的分級是「<xliff:g id="RATING">%1$s</xliff:g>」。如要觀看此節目,請輸入 PIN 碼"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"這個節目未分級。如要觀看此節目,請輸入你的 PIN 碼"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"請輸入您的 PIN"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"如要設定家長監護,請建立 PIN"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"輸入新的 PIN"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"該 PIN 錯誤,請再試一次。"</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"PIN 碼不符,請再試一次"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"請輸入你的郵遞區號。"</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"直播頻道應用程式會利用郵遞區號提供完整的電視頻道節目指南。"</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"請輸入你的郵遞區號"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"無效的郵遞區號"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"設定"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"自訂頻道清單"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"為您的節目指南選擇頻道"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"頻道來源"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"有可用的新頻道"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"家長監護"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"影片播放操作"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"在觀看時進行錄製,以便將直播節目暫停或倒轉。\n警告:這項功能會密集使用儲存空間,可能會因此縮短內部儲存空間的使用壽命。"</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"開放原始碼授權"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"開放原始碼授權"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"提供意見"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"版本"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"如要觀看這個頻道,請按向右鍵並輸入您的 PIN"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"如要觀看這個節目,請按向右鍵並輸入您的 PIN"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"這個節目未分級。\n如要觀看此節目,請按向右鍵並輸入你的 PIN 碼"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"這個節目的分級是「<xliff:g id="RATING">%1$s</xliff:g>」。\n如要觀看這個節目,請按向右鍵並輸入您的 PIN"</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"如要觀看這個頻道,請使用預設的直播電視應用程式。"</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"如要觀看這個節目,請使用預設的直播電視應用程式。"</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"這個節目未分級。\n如要觀看此節目,請使用預設的直播電視應用程式。"</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"這個節目的分級是「<xliff:g id="RATING">%1$s</xliff:g>」。\n如要觀看這個節目,請使用預設的直播電視應用程式。"</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"節目遭到封鎖"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"這個節目未分級"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"這個節目的分級是「<xliff:g id="RATING">%1$s</xliff:g>」。"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"僅限音訊"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"訊號微弱"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307">"按 [選取]"<b></b>" 即可使用 [電視選單]。"</string>
     <string name="msg_no_input" msgid="3897674146985427865">"找不到電視輸入裝置"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"找不到電視輸入裝置"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"不支援子母畫面"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"沒有可透過子母畫面顯示的輸入來源"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"協調器類型不適合;請啟動協調器類型電視輸入裝置專用的 Live TV 應用程式。"</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"協調失敗"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"找不到可以處理這個動作的應用程式。"</string>
@@ -226,6 +217,8 @@
       <item quantity="other">已預約錄製 %1$d 個節目</item>
       <item quantity="one">已預約錄製 %1$d 個節目</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"取消錄製"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"停止錄製"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"觀看"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"從頭開始播放"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"繼續播放"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"如果同一時段錄製的節目過多,系統只會錄製優先順序較高的節目。"</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"儲存"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"只排定錄製一次的項目優先順序最高"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"取消"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"取消"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"移除"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"停止"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"查看錄影時間表"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"只錄這一集"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"改錄這個節目"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"取消這項錄影預約"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"立即觀看"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"刪除錄影檔案…"</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"可錄影"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"已排定錄影時間"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"錄影衝突"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"錄製中"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"錄製失敗"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"正在讀取節目以建立錄影時間表"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"正在讀取節目"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"正在讀取節目資訊"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"查看最近的錄製項目"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》未錄製完成。"</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"《<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>》和《<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>》未錄製完成。"</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"《<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>》、《<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>》和《<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>》未錄製完成。"</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"儲存空間不足,因此《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》未錄製完成。"</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"儲存空間不足,因此《<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>》和《<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>》未錄製完成。"</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"儲存空間不足,因此《<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>》、《<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g>》和《<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g>》未錄製完成。"</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"DVR 需要更多儲存空間"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"你可以利用 DVR 錄製節目,但目前裝置儲存空間不足,因此無法使用 DVR。請連接 <xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB 以上的外接式磁碟,然後按照相關步驟將該磁碟格式化為裝置儲存空間。"</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"你可以利用 DVR 錄製節目,但目前裝置儲存空間不足,因此無法使用 DVR。請連接 <xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB 以上的外接式磁碟,然後按照相關步驟將該磁碟格式化為裝置儲存空間。"</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"儲存空間不足"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"儲存空間不足,因此無法錄製這個節目。請嘗試刪除一些現有的錄影檔案。"</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"無法存取儲存空間"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"無法存取部分 DVR 使用的儲存空間。請連接你先前使用的外接式磁碟以重新啟用 DVR。如果儲存空間已無法使用,你也可以選擇移除儲存空間。"</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"要移除儲存空間嗎?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"所有錄製內容和錄影時間表都不會保存下來。"</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"要停止錄影嗎?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"系統將儲存已錄製的內容。"</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"由於「<xliff:g id="PROGRAMNAME">%1$s</xliff:g>」與這個節目發生衝突,因此系統將停止錄製。已錄製的內容會保留下來。"</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"已排定錄影時間,但錄影時間發生衝突"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"已開始錄影,但發生衝突"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"系統將會錄製《<xliff:g id="PROGRAMNAME">%1$s</xliff:g>》。"</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"同一個節目已預約在 <xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g> 錄影。"</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"已錄影"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"這個節目已完成錄影並儲存在 DVR 媒體庫中。"</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"已排定影集錄製時間"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 個錄影時間。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 個錄影時間。由於發生時間衝突,因此系統將不會錄製其中 <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> 集節目。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。由於發生時間衝突,因此系統將不會錄製這集節目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_4">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> 個錄影時間。由於發生時間衝突,因此系統將不會錄製這個影集和其他影集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> 集節目。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。由於發生時間衝突,因此系統將不會錄製這個影集和其他影集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> 集節目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_3">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> 個錄影時間。由於發生時間衝突,因此系統將不會錄製其他影集的 1 集節目。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。由於發生時間衝突,因此系統將不會錄製其他影集的 1 集節目。</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="other">已為《<xliff:g id="SERIESNAME_4">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> 個錄影時間。由於發生時間衝突,因此系統將不會錄製其他影集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> 集節目。</item>
+      <item quantity="one">已為《<xliff:g id="SERIESNAME_1">%2$s</xliff:g>》排定 <xliff:g id="NUMBEROFRECORDINGS_0">%1$d</xliff:g> 個錄影時間。由於發生時間衝突,因此系統將不會錄製其他影集的 <xliff:g id="NUMBEROFCONFLICTEPISODES_2">%3$d</xliff:g> 集節目。</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"找不到錄製的節目。"</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"相關錄影"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(無節目說明)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="other">%1$d 個錄製項目</item>
       <item quantity="one">%1$d 個錄製項目</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"要停止建立影集錄製時間表嗎?"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"錄製完畢的集數會保存在 DVR 媒體庫中。"</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"停止"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"目前未播出任何劇集。"</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"目前沒有可供觀看的集數。\n系統會在節目播出時立即錄影。"</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="other">(%1$d 分鐘)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"今天:<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"明天:<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"分數"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"已錄製的節目"</string>
 </resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index ff1cfb3..f34cdbd 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -20,9 +20,8 @@
     <string name="audio_channel_mono" msgid="8812941280022167428">"i-mono"</string>
     <string name="audio_channel_stereo" msgid="5798223286366598036">"i-stereo"</string>
     <string name="menu_title_play_controls" msgid="2490237359425190652">"Izilawuli zokudlala"</string>
-    <string name="menu_title_channels" msgid="1801845517674690003">"Iziteshi zakamuva"</string>
+    <string name="menu_title_channels" msgid="1949045451672990132">"Iziteshi"</string>
     <string name="menu_title_options" msgid="7184594626814914022">"Izinketho ze-TV"</string>
-    <string name="menu_title_pip_options" msgid="4252934960762407689">"Izinketho ze-PIP"</string>
     <string name="play_controls_unavailable" msgid="8900698593131693148">"Izilawuli zokudlala azitholakali kulesi siteshi"</string>
     <string name="play_controls_description_play_pause" msgid="7225542861669250558">"Dlala noma umise isikhashana"</string>
     <string name="play_controls_description_fast_forward" msgid="4414963867482448652">"Ukudlulisa ngokushesha"</string>
@@ -35,33 +34,15 @@
     <string name="options_item_closed_caption" msgid="5945274655046367170">"Amazwibela avaliwe"</string>
     <string name="options_item_display_mode" msgid="7989243076748680140">"Imodi yesibonisi"</string>
     <string name="options_item_pip" msgid="3951350386626879645">"I-PIP"</string>
-    <string name="options_item_pip_on" msgid="4647247480009077381">"Vuliwe"</string>
-    <string name="options_item_pip_off" msgid="8799500161592387451">"Valiwe"</string>
     <string name="options_item_multi_audio" msgid="5118851311937896923">"Umsindo omningi"</string>
     <string name="options_item_more_channels" msgid="971040969622943300">"Thola iziteshi eziningi"</string>
     <string name="options_item_settings" msgid="7623205838542400074">"Izilungiselelo"</string>
-    <string name="pip_options_item_source" msgid="1050948525825308652">"Umthombo"</string>
-    <string name="pip_options_item_swap" msgid="7245362207353732048">"Shintsha"</string>
-    <string name="pip_options_item_swap_on" msgid="5647182616484983505">"Vuliwe"</string>
-    <string name="pip_options_item_swap_off" msgid="3023597229417709768">"Valiwe"</string>
-    <string name="pip_options_item_sound" msgid="3107034283791231648">"Umsindo"</string>
-    <string name="pip_options_item_sound_main" msgid="1063937534112558691">"Isisekelo"</string>
-    <string name="pip_options_item_sound_pip_window" msgid="435064142351853008">"Iwindil le-PIP"</string>
-    <string name="pip_options_item_layout" msgid="5126206342060967651">"Isakhiwo"</string>
-    <string name="pip_options_item_layout_bottom_right" msgid="5256839015192920238">"Phansi ngakwesokudla"</string>
-    <string name="pip_options_item_layout_top_right" msgid="3585067214787055279">"Phezulu ngakwesokudla"</string>
-    <string name="pip_options_item_layout_top_left" msgid="2173997010201637462">"Phezulu ngakwesokunxele"</string>
-    <string name="pip_options_item_layout_bottom_left" msgid="1727197877968915329">"Phansi ngakwesokunxele"</string>
-    <string name="pip_options_item_layout_side_by_side" msgid="9009784972740915779">"ingxenye nenxenye"</string>
-    <string name="pip_options_item_size" msgid="5662894110243750158">"Usayizi"</string>
-    <string name="pip_options_item_size_big" msgid="6303301565563444718">"Kukhulu"</string>
-    <string name="pip_options_item_size_small" msgid="7393731186585004206">"Kuncane"</string>
-    <string name="side_panel_title_pip_input_source" msgid="8722544967592970296">"Umthombo wokufaka"</string>
     <string name="input_long_label_for_tuner" msgid="3423514011918382209">"I-TV (I-antenna/Intambo)"</string>
     <string name="no_program_information" msgid="1049844207745145132">"Alukho ulwazi lohlelo"</string>
     <string name="program_title_for_no_information" msgid="384451471906070101">"Alukho ulwazi"</string>
     <string name="program_title_for_blocked_channel" msgid="5358005891746983819">"Isiteshi esivinjiwe"</string>
-    <string name="default_language" msgid="4122326459624337928">"Ulimi olungaziwa"</string>
+    <string name="multi_audio_unknown_language" msgid="8639884627225598143">"Ulimi olungaziwa"</string>
+    <string name="closed_caption_unknown_language" msgid="4745445516930229353">"Imibhalo engezansi evaliwe engu-%1$d"</string>
     <string name="side_panel_title_closed_caption" msgid="2513905054082568780">"Amazwibela avaliwe"</string>
     <string name="closed_caption_option_item_off" msgid="4824009036785647753">"Valiwe"</string>
     <string name="closed_caption_system_settings" msgid="1856974607743827178">"Yenza ngokwezifiso ukufometha"</string>
@@ -83,6 +64,7 @@
     <string name="edit_channels_group_divider_for_sd" msgid="5846195382266436167">"I-SD"</string>
     <string name="side_panel_title_group_by" msgid="1783176601425788939">"Qoqa nge-"</string>
     <string name="program_guide_content_locked" msgid="198056836554559553">"Lolu hlelo luvinjiwe"</string>
+    <string name="program_guide_content_locked_unrated" msgid="8665707501827594275">"Lolu hlelo alulinganiselwe"</string>
     <string name="program_guide_content_locked_format" msgid="514915272862967389">"Lolu hlelo lulinganiselwe nge-<xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="msg_no_setup_activity" msgid="7746893144640239857">"Kokufaka akusekeli ukuskena okuzenzakalelayo"</string>
     <string name="msg_unable_to_start_setup_activity" msgid="8402612466599977855">"Ayikwazi ukuqala ukuskena ngokuzenzakalela kwe-\'<xliff:g id="TV_INPUT">%s</xliff:g>\'"</string>
@@ -92,7 +74,6 @@
       <item quantity="other">%1$d iziteshi ezingeziwe</item>
     </plurals>
     <string name="msg_no_channel_added" msgid="2882586037409921925">"Azikho iziteshi ezingeziwe"</string>
-    <string name="input_selector_tuner_label" msgid="6631205039926880892">"I-Tuner"</string>
     <string name="menu_parental_controls" msgid="2474294054521345840">"Ukulawula kwabazali"</string>
     <string name="option_toggle_parental_controls_on" msgid="9122851821454622696">"Vuliwe"</string>
     <string name="option_toggle_parental_controls_off" msgid="7797910199040440618">"Valiwe"</string>
@@ -108,6 +89,8 @@
     <string name="other_countries" msgid="8342216398676184749">"Amanye amazwe"</string>
     <string name="option_no_locked_channel" msgid="2543094883927978444">"Lutho"</string>
     <string name="option_no_enabled_rating_system" msgid="4139765018454678381">"Lutho"</string>
+    <string name="unrated_rating_name" msgid="1387302638048393814">"Okungalinganiselwe"</string>
+    <string name="option_block_unrated_programs" msgid="1108474218158184706">"Vimbela izinhlelo ezingalinganiselwe"</string>
     <string name="option_rating_none" msgid="5204552587760414879">"Lutho"</string>
     <string name="option_rating_high" msgid="8898400296730158893">"Imikhawulo ephezulu"</string>
     <string name="option_rating_medium" msgid="6455853836426497151">"Imikhawulo emaphakathi"</string>
@@ -124,6 +107,7 @@
     <string name="pin_enter_unlock_channel" msgid="4797922378296393173">"Faka iphinikhodi yakho ukuze ubuke lesi siteshi"</string>
     <string name="pin_enter_unlock_program" msgid="7311628843209871203">"Faka iphinikhodi yakho ukuze ubuke lolu hlelo"</string>
     <string name="pin_enter_unlock_dvr" msgid="1637468108723176684">"Lolu hlelo lulinganiselwe ku-<xliff:g id="RATING">%1$s</xliff:g>. Faka iphini yakho ukuze ubuke lolu hlelo"</string>
+    <string name="pin_enter_unlock_dvr_unrated" msgid="3911986002480028829">"Lolu hlelo alulinganiselwe. Faka iphinikhodi yakho ukuze ubuke lolu hlelo"</string>
     <string name="pin_enter_pin" msgid="249314665028035038">"Faka iphinikhodi yakho"</string>
     <string name="pin_enter_create_pin" msgid="3385754356793309946">"Ukuze usethe izilawuli zomzali, dala iphinikhodi"</string>
     <string name="pin_enter_new_pin" msgid="1739471585849790384">"Faka iphinikhodi entsha"</string>
@@ -135,22 +119,31 @@
     </plurals>
     <string name="pin_toast_wrong" msgid="2126295626095048746">"Leyo phini ayilungile. Zama futhi."</string>
     <string name="pin_toast_not_match" msgid="4283624338659521768">"Zama futhi, iphinikhodi ayifani"</string>
+    <string name="postal_code_guidance_title" msgid="4144793072363879833">"Faka ikhodi yakho ye-ZIP."</string>
+    <string name="postal_code_guidance_description" msgid="4224511147377561572">"Uhlelo lokusebenza lweziteshi ezibukhoma luzosebenzisa ikhodi ye-ZIP ukuze lunikeze umhlahlandlela wohlelo ophelele weziteshi ze-TV."</string>
+    <string name="postal_code_action_description" msgid="4428720607051109105">"Faka ikhodi yakho ye-ZIP"</string>
+    <string name="postal_code_invalid_warning" msgid="923373584458340746">"Ikhodi ye-ZIP engavumelekile"</string>
     <string name="side_panel_title_settings" msgid="8244327316510918755">"Izilungiselelo"</string>
     <string name="settings_channel_source_item_customize_channels" msgid="6115770679732624593">"Yenza ngezifiso uhlu lweziteshi"</string>
     <string name="settings_channel_source_item_customize_channels_description" msgid="8966243790328235580">"Khetha iziteshi zomhlahlandlela wohlelo lwakho"</string>
     <string name="settings_channel_source_item_setup" msgid="4566190088656419070">"Imithombo yeziteshi"</string>
     <string name="settings_channel_source_item_setup_new_inputs" msgid="4845822152617430787">"Iziteshi ezintsha ziyatholakala"</string>
     <string name="settings_parental_controls" msgid="5449397921700749317">"Ukulawula kwabazali"</string>
+    <string name="settings_trickplay" msgid="7762730842781251582">"I-Timeshift"</string>
+    <string name="settings_trickplay_description" msgid="3060323976172182519">"Rekhoda ngenkathi ubukile ukuze uzokwazi ukumisa okwesikhashana noma ubuyisele emuva izinhlelo ezibukhoma.\nIsexwayiso: Lokhu kungehlisa impilo yesitoreji sangaphakathi ngokusetshenziswa kakhulu kwesitoreji."</string>
     <string name="settings_menu_licenses" msgid="1257646083838406103">"Amalayisense womthombo ovulekile"</string>
-    <string name="dialog_title_licenses" msgid="4471754920475076623">"Amalayisense womthombo ovulekile"</string>
+    <string name="settings_send_feedback" msgid="6897217561193701829">"Thumela impendulo"</string>
     <string name="settings_menu_version" msgid="2604030372029921403">"Inguqulo"</string>
     <string name="tvview_channel_locked" msgid="6486375335718400728">"Ukuze ubuke lesi siteshi, cindezela Kwesokudla uphinde ufake i-PIN yakho"</string>
     <string name="tvview_content_locked" msgid="391823084917017730">"Ukuze ubuke lolu hlelo, cindezela Kwesokudla uphinde ufake i-PIN yakho"</string>
+    <string name="tvview_content_locked_unrated" msgid="2273799245001356782">"Lolu hlelo alulinganiselwe.\nUkuze ubuke lolu hlelo, cindezela Kwesokudla bese ufaka iphinikhodi yakho"</string>
     <string name="tvview_content_locked_format" msgid="3741874636031338247">"Lolu hlelo lulinganiselwe ngo-<xliff:g id="RATING">%1$s</xliff:g>.\nUkuze ubuke lolu hlelo, cindezela Kwesokudla uphinde ufake i-PIN yakho."</string>
     <string name="tvview_channel_locked_no_permission" msgid="677653135227590620">"Ukuze ubuke lesi siteshi, sebenzisa uhlelo lokusebenza lwe-TV ebukhoma."</string>
     <string name="tvview_content_locked_no_permission" msgid="2279126235895507764">"Ukuze ubuke lolu hlelo, sebenzisa uhlelo lokusebenza oluzenzakalelayo lwe-TV ebukhoma."</string>
+    <string name="tvview_content_locked_unrated_no_permission" msgid="4056090982858455110">"Lolu hlelo alulinganiselwe.\nUkuze ubuke lolu hlelo, sebenzisa uhlelo lokusebenza oluzenzakalelayo lwe-TV elibukhoma."</string>
     <string name="tvview_content_locked_format_no_permission" msgid="5690794624572767106">"Lolu hlelo lulinganiselwe ngokungu-<xliff:g id="RATING">%1$s</xliff:g>.\nUkuze ubuke lolu hlelo, sebenzisa uhlelo lokusebenza lwe-TV ebukhoma."</string>
     <string name="shrunken_tvview_content_locked" msgid="7686397981042364446">"Uhlelo luvinjiwe"</string>
+    <string name="shrunken_tvview_content_locked_unrated" msgid="4586881678635960742">"Lolu hlelo alulinganiselwe"</string>
     <string name="shrunken_tvview_content_locked_format" msgid="3720284198877900916">"Lolu hlelo lulinganiselwe nge-<xliff:g id="RATING">%1$s</xliff:g>"</string>
     <string name="tvview_msg_audio_only" msgid="1356866203687173329">"Umsindo kuphela"</string>
     <string name="tvview_msg_weak_signal" msgid="1095050812622908976">"Isignali engaqinile"</string>
@@ -181,8 +174,6 @@
     <string name="intro_description" msgid="7806473686446937307"><b>"Cindezela okuthi KHETHA"</b>" ukuze ufinyelele imenyu ye-TV."</string>
     <string name="msg_no_input" msgid="3897674146985427865">"Akukho kokufaka kwe-TV okutholakele"</string>
     <string name="msg_no_specific_input" msgid="2688885987104249852">"Ayikwazi ukuthola kokufaka kwe-TV"</string>
-    <string name="msg_no_pip_support" msgid="161508628996629445">"I-PIP ayisekelwe"</string>
-    <string name="msg_no_available_input_by_pip" msgid="7038191654524679666">"Akutholakali okokufaka okungaboniswa nge-PIP"</string>
     <string name="msg_not_passthrough_input" msgid="4502101097091087411">"uhlobo le-Tuner alufanelekile; Sicela uqalise uhlelo lokusebenza leziteshi ezibukhoma lokufakwayo kwe-TV yohlobo le-tuner."</string>
     <string name="msg_tune_failed" msgid="3277419551849972252">"Ukushuna kwehlulekile"</string>
     <string name="msg_missing_app" msgid="8291542072400042076">"Alukho uhlelo lokusebenza olutholakalele ukuphatha lesi senzo."</string>
@@ -226,6 +217,8 @@
       <item quantity="one">%1$d ukurekhodwa okushejuliwe</item>
       <item quantity="other">%1$d ukurekhodwa okushejuliwe</item>
     </plurals>
+    <string name="dvr_detail_cancel_recording" msgid="542538232330174145">"Khansela ukurekhoda"</string>
+    <string name="dvr_detail_stop_recording" msgid="3599488040374849367">"Misa ukurekhoda"</string>
     <string name="dvr_detail_watch" msgid="7085694764364338215">"Buka"</string>
     <string name="dvr_detail_play_from_beginning" msgid="8475543568260411836">"Dlala kusuka ekuqaleni"</string>
     <string name="dvr_detail_resume_play" msgid="875591300274416373">"Qalisa ukudlala"</string>
@@ -258,9 +251,6 @@
     <string name="dvr_priority_description" msgid="8362040921417154645">"Uma kunezinhlelo eziningi kakhulu okufanele zirekhodwe ngesikhathi esisodwa, yilezo ezinokukhetha okuphezulu ezizorekhodwa."</string>
     <string name="dvr_priority_button_action_save" msgid="4773524273649733008">"Londoloza"</string>
     <string name="dvr_priority_action_one_time_recording" msgid="8174297042282719478">"Ukurekhoda kwesikhathi esisodwa kunokubaluleka okuphezulu kakhulu"</string>
-    <string name="dvr_action_cancel" msgid="8094060199570272625">"Khansela"</string>
-    <string name="dvr_action_error_cancel" msgid="6822474458738023531">"Khansela"</string>
-    <string name="dvr_action_error_forget_storage" msgid="5869994565663655638">"Khohlwa"</string>
     <string name="dvr_action_stop" msgid="1378723485295471381">"Misa"</string>
     <string name="dvr_action_view_schedules" msgid="7442990695392774263">"Buka ishejuli yokurekhoda"</string>
     <string name="dvr_action_record_episode" msgid="8596182676610326327">"Lolu hlelo olulodwa"</string>
@@ -270,25 +260,28 @@
     <string name="dvr_action_record_instead" msgid="6821164728752215738">"Rekhoda lokhu esikhundleni"</string>
     <string name="dvr_action_record_cancel" msgid="8644254745772185288">"Khansela lokhu kurekhoda"</string>
     <string name="dvr_action_watch_now" msgid="7181211920959075976">"Bukela njengamanje"</string>
+    <string name="dvr_action_delete_recordings" msgid="850785346795261671">"Susa ukurekhodwa..."</string>
     <string name="dvr_epg_program_recordable" msgid="609229576209476903">"Okungarekhodeka"</string>
     <string name="dvr_epg_program_recording_scheduled" msgid="1367741844291055016">"Ukurekhoda kushejuliwe"</string>
     <string name="dvr_epg_program_recording_conflict" msgid="4827911748865195373">"Ukungqubuzana kokurekhoda"</string>
     <string name="dvr_epg_program_recording_in_progress" msgid="2158340443975313745">"Iyarekhoda"</string>
     <string name="dvr_epg_program_recording_failed" msgid="5589124519442328896">"Ukurekhoda kuhlulekile"</string>
-    <string name="dvr_schedule_progress_message_reading_programs" msgid="6502513156469172313">"Ifunda izinhlelo ukuze idale amashejuli okurekhoda"</string>
-    <string name="dvr_series_schedules_progress_message_reading_programs" msgid="7221275889560136115">"Izinhlelo ezifundayo"</string>
-    <!-- no translation found for dvr_series_schedules_progress_message_updating_programs (6670286486601662465) -->
-    <skip />
+    <string name="dvr_series_progress_message_reading_programs" msgid="2961615820635219355">"Izinhlelo ezifundayo"</string>
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings" msgid="137918938589787623">"Buka ukurekhoda kwakamuva"</string>
+    <string name="dvr_error_insufficient_space_title_one_recording" msgid="759510175792505150">"Ukurekhoda kwe-<xliff:g id="PROGRAMNAME">%1$s</xliff:g> akuphelele."</string>
+    <string name="dvr_error_insufficient_space_title_two_recordings" msgid="5518578722556227631">"Ukurekhoda kwe-<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ne-<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> akuphelele."</string>
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings" msgid="5104901174884754363">"Ukurekhoda kwe-<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> and <xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> akuphelele."</string>
+    <string name="dvr_error_insufficient_space_description_one_recording" msgid="9092549220659026111">"Ukurekhoda kwe-<xliff:g id="PROGRAMNAME">%1$s</xliff:g> akuqedanga ngenxa yesitoreji esingaphelele."</string>
+    <string name="dvr_error_insufficient_space_description_two_recordings" msgid="7712799694720979003">"Ukurekhoda kwe-<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g> ne-<xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> akuqedanga ngenxa yesitoreji esingaphelele."</string>
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings" msgid="7877855707777832128">"Ukurekhoda kwe-<xliff:g id="PROGRAMNAME_1">%1$s</xliff:g>, <xliff:g id="PROGRAMNAME_2">%2$s</xliff:g> ne-<xliff:g id="PROGRAMNAME_3">%3$s</xliff:g> akuqedanga ngenxa yesitoreji esingaphelele."</string>
     <string name="dvr_error_small_sized_storage_title" msgid="5020225460011469011">"I-DVR idinga isitoreji esiningi"</string>
-    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Uzokwazi ukurekhoda izinhlelo nge-DVR. Kodwa asikho isitoreji esanele kudivayisi yakho manje ukuze i-DVR isebenze. Sicela uxhume idrayivu yangaphandle engu-<xliff:g id="STORAGE_SIZE">%1$s</xliff:g>GB noma enkulu bese ulandela izinyathelo uyifomethe njengesitoreji sedivayisi."</string>
+    <string name="dvr_error_small_sized_storage_description" msgid="8909789097974895119">"Uzokwazi ukurekhoda izinhlelo nge-DVR. Kodwa asikho isitoreji esanele kudivayisi yakho manje ukuze i-DVR isebenze. Sicela uxhume idrayivu yangaphandle engu-<xliff:g id="STORAGE_SIZE">%1$d</xliff:g>GB noma enkulu bese ulandela izinyathelo uyifomethe njengesitoreji sedivayisi."</string>
+    <string name="dvr_error_no_free_space_title" msgid="881897873932403512">"Indawo yokubeka ayanele"</string>
+    <string name="dvr_error_no_free_space_description" msgid="6406038381803431564">"Lolu hlelo ngeke lirekhodwe ngoba asikho isitoreji esanele. Zama ukususa ukurekhoda okukhona."</string>
     <string name="dvr_error_missing_storage_title" msgid="691914341845362669">"Isitoreji esilahlekile"</string>
-    <string name="dvr_error_missing_storage_description" msgid="1036680750969954236">"Esinye sesitoreji esisetshenziswa yi-DVR silahlekile. Sicela uxhume idrayivu engaphandle oyisebenzise ngaphambilini ukuze uphinde unike amandla i-DVR. Okunye, ungakhetha ukukhohlwa isitoreji uma singasatholakali."</string>
-    <string name="dvr_error_forget_storage_title" msgid="4996547357826788002">"Khohlwa isitoreji?"</string>
-    <string name="dvr_error_forget_storage_description" msgid="3973761741009546142">"Konke okuqukethwe kwakho okurekhodiwe namashejuli azolahleka."</string>
     <string name="dvr_stop_recording_dialog_title" msgid="2587018956502704278">"Misa ukurekhoda?"</string>
     <string name="dvr_stop_recording_dialog_description" msgid="4637830189399967761">"Okuqukethwe okurekhodiwe kuzolondolozwa."</string>
-    <!-- no translation found for dvr_stop_recording_dialog_description_on_conflict (7876857267536083760) -->
-    <skip />
+    <string name="dvr_stop_recording_dialog_description_on_conflict" msgid="7876857267536083760">"Ukurekhodwa kwe-<xliff:g id="PROGRAMNAME">%1$s</xliff:g> kuzomiswa ngoba kugqubuzana nalolu hlelo. Okuqukethwe okurekhodiwe ngeke kulondolozwe."</string>
     <string name="dvr_program_conflict_dialog_title" msgid="109323740107060379">"Ukurekhoda kushejuliwe kodwa kunokugqubuzana"</string>
     <string name="dvr_channel_conflict_dialog_title" msgid="7461033430572027786">"Ukurekhoda kuqalile kodwa kunokugxubuzana"</string>
     <string name="dvr_program_conflict_dialog_description_prefix" msgid="5520062013211648196">"<xliff:g id="PROGRAMNAME">%1$s</xliff:g> izorekhodwa."</string>
@@ -306,17 +299,29 @@
     <string name="dvr_already_scheduled_dialog_description" msgid="8170126125996414810">"Uhlelo olufanayo seluvele luhlelwe ukurekhodwa ngo-<xliff:g id="PROGRAMSTARTTIME">%1$s</xliff:g>."</string>
     <string name="dvr_already_recorded_dialog_title" msgid="2760294707162057216">"Sekuvele kurekhodiwe"</string>
     <string name="dvr_already_recorded_dialog_description" msgid="8966051583682746434">"Lolu hlelo seluvele lurekhodiwe. Lutholakala kulabhulali ye-DVR."</string>
-    <!-- no translation found for dvr_series_recording_dialog_title (3521956660855853797) -->
-    <skip />
-    <!-- no translation found for dvr_series_recording_scheduled_no_conflict (2796926724821316879) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_this_series_conflict (2800805130979023066) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_one_conflict (3632394665556633158) -->
-    <!-- no translation found for dvr_series_recording_scheduled_this_and_other_series_conflict (2331412040101938479) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_one_conflict (5213169239215104024) -->
-    <!-- no translation found for dvr_series_recording_scheduled_only_other_series_conflict (5159645486201045330) -->
+    <string name="dvr_series_recording_dialog_title" msgid="3521956660855853797">"Ukurekhodwa kochungechunge kuhleliwe"</string>
+    <plurals name="dvr_series_scheduled_no_conflict" formatted="false" msgid="6909096418632555251">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_3">%2$s</xliff:g>.</item>
+    </plurals>
+    <plurals name="dvr_series_recording_scheduled_only_this_series_conflict" formatted="false" msgid="2341548158607418515">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> kwazo ngeke kurekhodwe ngenxa yokushayisana.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_3">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTRECORDINGS">%3$d</xliff:g> kwazo ngeke kurekhodwe ngenxa yokushayisana.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict" formatted="false" msgid="6123651855499916154">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> iziqephu zalo chungechunge nolunye uchungechunge ngeke zirekhodwe ngenxa yokushayisana.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> iziqephu zalo chungechunge nolunye uchungechunge ngeke zirekhodwe ngenxa yokushayisana.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict" formatted="false" msgid="8628389493339609682">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 isiqephu solunye uchungechunge ngeke sirekhodwe ngenxa yokushayisana.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_2">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_3">%2$s</xliff:g>. 1 isiqephu solunye uchungechunge ngeke sirekhodwe ngenxa yokushayisana.</item>
+    </plurals>
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts" formatted="false" msgid="1601104768354168073">
+      <item quantity="one"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> iziqephu zolunye uchungechunge ngeke zize zirekhodwe ngenxa yokushayisana.</item>
+      <item quantity="other"><xliff:g id="NUMBEROFRECORDINGS_3">%1$d</xliff:g> ukurekhodwa kushejulelwe i-<xliff:g id="SERIESNAME_4">%2$s</xliff:g>. <xliff:g id="NUMBEROFCONFLICTEPISODES_5">%3$d</xliff:g> iziqephu zolunye uchungechunge ngeke zize zirekhodwe ngenxa yokushayisana.</item>
+    </plurals>
     <string name="dvr_program_not_found" msgid="3282879532038010202">"Uhlelo olurekhodiwe alutholakali."</string>
     <string name="dvr_playback_related_recordings" msgid="6978658039329924961">"Ukurekhodwa okuhlobene"</string>
-    <string name="dvr_msg_no_program_description" msgid="2521723281247322645">"(Ayikho incazelo yohlelo)"</string>
     <plurals name="dvr_schedules_section_subtitle" formatted="false" msgid="9180744010405976007">
       <item quantity="one">%1$d ukurekhoda</item>
       <item quantity="other">%1$d ukurekhoda</item>
@@ -336,6 +341,7 @@
     <string name="dvr_series_schedules_stop_dialog_title" msgid="4975886236535334420">"Misa ukurekhodwa kochungechunge"</string>
     <string name="dvr_series_schedules_stop_dialog_description" msgid="7547266283366940085">"Iziqephu ezirekhodiwe zizohlala zitholakala kulabhulali ye-DVR."</string>
     <string name="dvr_series_schedules_stop_dialog_action_stop" msgid="2351839914865142478">"Misa"</string>
+    <string name="dvr_series_schedules_stopped_empty_state" msgid="1464244804664395151">"Azikho iziqephu ezisemoyeni okwamanje."</string>
     <string name="dvr_series_schedules_empty_state" msgid="3407962945399698707">"Azikho iziqephu ezitholakalayo.\nZizorekhodwa uma zitholakala."</string>
     <plurals name="dvr_schedules_recording_duration" formatted="false" msgid="3701771573063918552">
       <item quantity="one">(%1$d amaminithi)</item>
@@ -347,4 +353,5 @@
     <string name="dvr_date_today_time" msgid="8359696776305244535">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> namhlanje"</string>
     <string name="dvr_date_tomorrow_time" msgid="8364654556105292594">"<xliff:g id="TIME_RANGE">%1$s</xliff:g> kusasa"</string>
     <string name="program_guide_critic_score" msgid="340530743913585150">"Isikolo"</string>
+    <string name="recorded_programs_preview_channel" msgid="890404366427245812">"Izinhlelo ezirekhodiwe"</string>
 </resources>
diff --git a/res/values/attr.xml b/res/values/attr.xml
deleted file mode 100644
index 1261ea4..0000000
--- a/res/values/attr.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<resources>
-    <declare-styleable name="CurrentProgramState" >
-        <attr name="state_current_program" format="boolean" />
-    </declare-styleable>
-    <declare-styleable name="ProgramTooWideState" >
-        <attr name="state_program_too_wide" format="boolean" />
-    </declare-styleable>
-</resources>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
new file mode 100644
index 0000000..a26a9ef
--- /dev/null
+++ b/res/values/attrs.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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.
+  -->
+
+<resources>
+    <declare-styleable name="CurrentProgramState" >
+        <attr name="state_current_program" format="boolean" />
+    </declare-styleable>
+    <declare-styleable name="ProgramTooWideState" >
+        <attr name="state_program_too_wide" format="boolean" />
+    </declare-styleable>
+    <!-- XML attributes that describe the
+         {@link com.android.tv.dvr.ui.FadeBackground FadeBackground} transition. The
+         attributes of the {@link android.R.styleable#Transition Transition} resource are available
+         in addition to the specific attributes of FadeBackground described here. -->
+    <declare-styleable name="FadeBackground">
+        <!-- Equivalent to <code>transitionVisibilityMode</code>, fadingMode works only with the
+             FadeBackground transition. -->
+        <attr name="fadingMode">
+            <!-- FadeBackground will only fade appearing items in. -->
+            <enum name="fade_in" value="1" />
+            <!-- FadeBackground will only fade disappearing items out. -->
+            <enum name="fade_out" value="2" />
+        </attr>
+    </declare-styleable>
+
+    <!-- XML attributes that describe the
+         {@link com.android.tv.menu.widget.PlaybackProgressBar PlaybackProgressBar} widget.
+         The attributes of the {@link com.android.internal.R.styleable.View View} resources are
+         available in addition to the specific attributes of PlaybackProgressBar described here. -->
+    <declare-styleable name="PlaybackProgressBar">
+        <!-- Drawable used for the progress mode. -->
+        <attr name="progressDrawable" format="reference" />
+    </declare-styleable>
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index b6b4056..e0a0b99 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -109,11 +109,11 @@
 
     <!-- TV view -->
     <color name="tvview_block_text_color">#80EEEEEE</color>
+    <color name="tvview_block_image_color_filter">#99000000</color>
 
     <!-- Channel banner -->
     <color name="channel_banner_text_color">#FFEEEEEE</color>
     <color name="channel_banner_episode_text_color">#B3EEEEEE</color>
-    <color name="channel_banner_secondary_input_label_color">#B3EEEEEE</color>
     <color name="channel_banner_dim_text_color">#80EEEEEE</color>
 
     <!-- Keypad channel switch -->
@@ -121,7 +121,7 @@
 
     <!-- Select input -->
     <color name="select_input_text_color_primary">@color/channel_banner_text_color</color>
-    <color name="select_input_text_color_secondary">@color/channel_banner_secondary_input_label_color</color>
+    <color name="select_input_text_color_secondary">#B3EEEEEE</color>
     <color name="select_input_text_color_disabled">#4DEEEEEE</color>
 
     <!-- Recommendation cards in LeanbackLauncher -->
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 8d9e45e..9d8941f 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -16,8 +16,12 @@
   -->
 
 <resources>
+     <!-- from https://developer.android.com/training/tv/start/layouts.html#structure -->
+    <dimen name="vertical_overscan_safe_margin">27dp</dimen>
+    <dimen name="horizontal_overscan_safe_margin">48dp</dimen>
+
     <!-- Main menu -->
-    <dimen name="menu_margin_top">@dimen/menu_enter_offset_y_negative</dimen>
+    <dimen name="menu_margin_top">-32dp</dimen>
     <dimen name="menu_margin_bottom_min">27dp</dimen>
     <dimen name="menu_row_align_from_bottom">124dp</dimen>
     <dimen name="menu_row_title_width">300dp</dimen>
@@ -41,7 +45,6 @@
     <dimen name="menu_row_title_text_size_deselected">16sp</dimen>
     <dimen name="menu_inter_card_spacing">8dp</dimen>
     <dimen name="menu_enter_offset_y">32dp</dimen>
-    <dimen name="menu_enter_offset_y_negative">-32dp</dimen>
     <dimen name="menu_exit_offset_y">32dp</dimen>
     <dimen name="menu_row_scroll_up_anim_offset">32dp</dimen>
 
@@ -102,7 +105,6 @@
     <dimen name="action_card_icon_width">32dp</dimen>
     <dimen name="action_card_icon_height">32dp</dimen>
     <dimen name="action_card_icon_padding">10dp</dimen>
-    <dimen name="action_card_padding">12dp</dimen>
     <dimen name="action_card_label_font_size">16sp</dimen>
     <dimen name="action_card_state_font_size">12sp</dimen>
 
@@ -115,7 +117,6 @@
     <dimen name="side_panel_header_padding_top">27dp</dimen>
     <dimen name="side_panel_header_elevation">4dp</dimen>
     <dimen name="side_panel_header_text_size">24sp</dimen>
-    <dimen name="side_panel_list_padding_top">0dp</dimen>
     <dimen name="side_panel_list_padding_bottom">48dp</dimen>
     <dimen name="side_panel_list_vertical_margin">0dp</dimen>
     <dimen name="side_panel_enter_offset_x">100dp</dimen>
@@ -147,7 +148,6 @@
 
     <!-- Program guide -->
     <dimen name="program_guide_shift_start_to_end_x">238dp</dimen>
-    <dimen name="program_guide_shift_end_to_start_x">-238dp</dimen>
     <dimen name="program_guide_side_panel_width">270dp</dimen>
     <dimen name="program_guide_side_panel_margin_start">-238dp</dimen>
     <dimen name="program_guide_side_panel_padding_start">56dp</dimen>
@@ -193,7 +193,7 @@
     <dimen name="program_guide_table_header_row_height">40dp</dimen>
     <dimen name="program_guide_table_header_row_font_size">16sp</dimen>
     <dimen name="program_guide_table_header_row_fade_length">24dp</dimen>
-    <dimen name="program_guide_table_header_row_overlap">-52dp</dimen>
+    <dimen name="program_guide_table_header_row_overlap">-72dp</dimen>
     <dimen name="program_guide_table_item_row_height">64dp</dimen>
     <dimen name="program_guide_table_item_padding">16dp</dimen>
     <dimen name="program_guide_table_item_compound_drawable_padding">8dp</dimen>
@@ -244,23 +244,9 @@
     <dimen name="shrunken_tvview_block_icon_height">60dp</dimen>
     <dimen name="shrunken_tvview_block_vertical_spacing">24dp</dimen>
 
-    <!-- PIP view -->
-    <dimen name="pipview_margin_horizontal">56dp</dimen>
-    <dimen name="pipview_margin_top">27dp</dimen>
-    <dimen name="pipview_margin_bottom">27dp</dimen>
-    <dimen name="pipview_small_size_width">240dp</dimen>
-    <dimen name="pipview_small_size_height">135dp</dimen>
-    <dimen name="pipview_large_size_width">384dp</dimen>
-    <dimen name="pipview_large_size_height">216dp</dimen>
-
-    <!-- PAP View -->
-    <dimen name="papview_margin_horizontal">20dp</dimen>
-    <dimen name="papview_spacing">24dp</dimen>
-
     <!-- Edit channels -->
     <dimen name="shrunken_tvview_margin_start">56dp</dimen>
     <dimen name="shrunken_tvview_margin_end">32dp</dimen>
-    <dimen name="shrunken_tvview_height">288dp</dimen>
 
     <!-- Channel banner -->
     <dimen name="channel_banner_width">696dp</dimen>
@@ -274,7 +260,7 @@
     <dimen name="channel_banner_channel_logo_height">44dp</dimen>
     <dimen name="channel_banner_channel_logo_margin_start">8dp</dimen>
     <dimen name="channel_banner_input_logo_size">16dp</dimen>
-    <dimen name="channel_banner_program_description_width">536dp</dimen>
+    <dimen name="channel_banner_program_description_width">456dp</dimen>
     <dimen name="channel_banner_program_large_text_size">28sp</dimen>
     <dimen name="channel_banner_program_medium_text_size">20sp</dimen>
     <dimen name="channel_banner_program_large_margin_top">-10sp</dimen>
@@ -290,6 +276,7 @@
 
     <!-- Input banner -->
     <dimen name="input_banner_item_height">48dp</dimen>
+    <dimen name="input_banner_item_label_max_width">324dp</dimen>
 
     <!-- Keypad channel switch -->
     <dimen name="keypad_channel_switch_channel_number_text_size">
@@ -336,9 +323,7 @@
 
     <!-- DVR screens -->
     <eat-comment />
-    <dimen name="dvr_card_layout_width">196dp</dimen>
-
-    <!--DVR schedules list-->
+    <!-- DVR schedules list -->
     <dimen name="dvr_schedules_layout_padding">132dp</dimen>
     <dimen name="dvr_schedules_row_divider_height">1dp</dimen>
     <dimen name="dvr_schedules_item_width">960dp</dimen>
@@ -349,9 +334,7 @@
     <dimen name="dvr_schedules_item_time_start_padding">32dp</dimen>
     <dimen name="dvr_schedules_item_time_margin">14dp</dimen>
     <dimen name="dvr_schedules_item_info_top_margin">15dp</dimen>
-    <dimen name="dvr_schedules_item_conflict_info_top_margin">12dp</dimen>
     <dimen name="dvr_schedules_item_conflict_info_bottom_margin">15dp</dimen>
-    <dimen name="dvr_schedules_item_schedule_width">56dp</dimen>
     <dimen name="dvr_schedules_item_delete_width">46dp</dimen>
     <dimen name="dvr_schedules_item_section_margin">32dp</dimen>
     <dimen name="dvr_schedules_item_icon_size">18dp</dimen>
@@ -361,26 +344,31 @@
     <dimen name="dvr_schedules_header_margin_bottom">24dp</dimen>
     <dimen name="dvr_schedules_header_subtitle_margin_top">5dp</dimen>
     <dimen name="dvr_schedules_header_icon_container_width">143dp</dimen>
-    <dimen name="dvr_schedules_header_icon_size">32dp</dimen>
     <dimen name="dvr_schedules_header_icon_horizontal_margin">12dp</dimen>
     <dimen name="dvr_schedules_warning_icon_padding">4dp</dimen>
 
-    <!-- card width - margin-->
-    <dimen name="dvr_card_image_layout_width">192dp</dimen>
-    <dimen name="dvr_card_image_layout_height">108dp</dimen>
-    <dimen name="dvr_card_progress_height">2dp</dimen>
+    <!-- DVR Library -->
+    <dimen name="dvr_library_expanded_row_height">175dp</dimen>
+    <dimen name="dvr_library_card_image_layout_width">144dp</dimen>
+    <dimen name="dvr_library_card_image_layout_height">108dp</dimen>
+    <dimen name="dvr_library_card_progress_height">2dp</dimen>
+    <dimen name="dvr_library_card_folded_title_height">20dp</dimen>
+    <dimen name="dvr_library_card_expanded_title_height">36.5dp</dimen>
 
     <!-- DVR playback fragment -->
-    <dimen name="dvr_related_recordings_width">146dp</dimen>
-    <dimen name="dvr_related_recordings_height">82dp</dimen>
+    <dimen name="dvr_related_recordings_width">108dp</dimen>
+    <dimen name="dvr_related_recordings_height">81dp</dimen>
     <!-- This value is used to adjust position of DVR playback controls row when there is no
          program description -->
     <dimen name="dvr_playback_controls_extra_padding_top">27.5dp</dimen>
-    <!-- This value is used to adjust position of DVR playback overlay fragment when there is no
-         related recordings -->
-    <dimen name="dvr_playback_fragment_extra_padding_top">48dp</dimen>
-    <dimen name="lb_playback_controls_padding_top">265dp</dimen>
-    <dimen name="lb_playback_controls_padding_bottom">40dp</dimen>
+    <!-- This value is used to adjust the vertical position of DVR playback overlay fragment -->
+    <dimen name="dvr_playback_overlay_padding_top_base">36dp</dimen>
+    <!-- This value is used to adjust the vertical position of DVR playback overlay fragment when
+         there is no related recordings -->
+    <dimen name="dvr_playback_overlay_padding_top_no_related_row">44dp</dimen>
+    <!-- This value is used to adjust the vertical position of DVR playback overlay fragment when
+         there is no secondary controls row -->
+    <dimen name="dvr_playback_overlay_padding_top_no_secondary_row">4dp</dimen>
 
     <!-- details fragment -->
     <dimen name="dvr_details_poster_width">219dp</dimen>
@@ -390,6 +378,7 @@
     <dimen name="dvr_deletion_check_mark_margin">20dp</dimen>
     <dimen name="dvr_details_overview_description_margin_start">12dp</dimen>
     <dimen name="dvr_details_overview_description_margin_end">12dp</dimen>
+    <dimen name="dvr_details_description_under_subtitle_baseline_margin">30dp</dimen>
     <!-- Below values are used to avoid detail titles' layout changing with two-line titles -->
     <dimen name="dvr_details_description_title_resized_text_size">34sp</dimen>
     <dimen name="dvr_details_description_title_padding_adjust_top">0dp</dimen>
@@ -401,4 +390,8 @@
          button actions list width = 138dp (weight = 0.39) -->
     <item name="dvr_settings_button_actions_list_width_weight" format="float" type="dimen">0.39</item>
     <item name="dvr_settings_guidedactions_width_weight" format="float" type="string">1.15</item>
+
+    <!-- Preview channel logo size -->
+    <dimen name="preview_channel_logo_width">80dp</dimen>
+    <dimen name="preview_channel_logo_height">80dp</dimen>
 </resources>
diff --git a/res/values/google-services.xml b/res/values/google-services.xml
deleted file mode 100755
index 379a345..0000000
--- a/res/values/google-services.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<resources>
-  <string name="firebase_database_url" translatable="false">https://live-channels-1237.firebaseio.com</string>
-  <string name="gcm_defaultSenderId" translatable="false">399597460505</string>
-  <string name="google_api_key" translatable="false">AIzaSyDK2BtNulo2ltWIogD64y1hBWKrdg9Sa7k</string>
-  <string name="google_crash_reporting_api_key" translatable="false">AIzaSyDK2BtNulo2ltWIogD64y1hBWKrdg9Sa7k</string>
-  <string name="google_app_id" translatable="false">1:399597460505:android:6c699100869b1467</string>
-</resources>
diff --git a/res/values/integers.xml b/res/values/integers.xml
index 81ccbeb..003344e 100644
--- a/res/values/integers.xml
+++ b/res/values/integers.xml
@@ -35,7 +35,10 @@
     <integer name="menu_row_selection_anim_duration">250</integer>
     <integer name="menu_previous_contents_fade_out_duration">50</integer>
     <integer name="menu_current_contents_fade_in_duration">200</integer>
-    
+
+    <!-- Option item -->
+    <integer name="option_item_description_max_lines">3</integer>
+
     <!-- Side panel -->
     <integer name="side_panel_show_duration">60000</integer>
     <integer name="side_panel_anim_duration">250</integer>
@@ -74,6 +77,9 @@
     <integer name="pin_dialog_exit_offset_y">32</integer>
     <integer name="pin_number_scroll_duration">250</integer>
 
+    <!-- Trickplay Setting -->
+    <integer name="trickplay_description_max_lines">5</integer>
+
     <!-- Max recycle view pool size -->
     <integer name="max_recycled_view_pool_epg_table_item">50</integer>
     <integer name="max_recycled_view_pool_epg_table_row">15</integer>
@@ -87,4 +93,5 @@
 
     <!-- DVR library -->
     <integer name="dvr_details_full_text_animation_duration">500</integer>
+    <integer name="dvr_card_title_max_lines_folded">1</integer>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a58f2d3..57049ab 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -35,6 +35,12 @@
     <!-- Description of an application permission, listed so the user can choose
         whether they want to allow the application to do this. -->
     <string name="permdesc_receiveInputEvent" translatable="false">Allows the app to receive input events from Live TV app</string>
+    <!-- Title of an application permission, listed so the user can choose
+        whether they want to allow the application to do this. -->
+    <string name="permlab_customizeTvApp" translatable="false">customize Live TV app</string>
+    <!-- Description of an application permission, listed so the user can choose
+        whether they want to allow the application to do this. -->
+    <string name="permdesc_customizeTvApp" translatable="false">Allows the app to customize Live TV app</string>
 
     <!-- Program information, mainly used for channel banner and program guide. -->
     <eat-comment />
@@ -63,11 +69,9 @@
          The play means a playback of video and audio. [CHAR LIMIT=NONE] -->
     <string name="menu_title_play_controls">Play controls</string>
     <!-- Title of the channels row in the main menu. [CHAR LIMIT=NONE] -->
-    <string name="menu_title_channels">Recent channels</string>
+    <string name="menu_title_channels">Channels</string>
     <!-- Title of the TV option row in the main menu. [CHAR LIMIT=NONE] -->
     <string name="menu_title_options">TV options</string>
-    <!-- Title of the PIP option row in the main menu. [CHAR LIMIT=NONE] -->
-    <string name="menu_title_pip_options">PIP options</string>
 
     <!-- Play speed of 2X, 3X, 4X, 5X -->
     <string name="play_controls_speed" translatable="false">%1$dX</string>
@@ -101,12 +105,6 @@
     <string name="options_item_display_mode">Display mode</string>
     <!-- Label of "PIP (Picture in picture)" item in the TV option row. [CHAR LIMIT=17] -->
     <string name="options_item_pip">PIP</string>
-    <!-- Description of the "PIP" item in the TV option row indicating that the currently the PIP
-         is turned on. [CHAR LIMIT=17] -->
-    <string name="options_item_pip_on">On</string>
-    <!-- Description of the "PIP" item in the TV option row indicating that the currently the PIP
-         is turned off. [CHAR LIMIT=20] -->
-    <string name="options_item_pip_off">Off</string>
     <!-- Label of "Multi audio" item in the TV option row. [CHAR LIMIT=17] -->
     <string name="options_item_multi_audio">Multi-audio</string>
     <!-- Label of "Get more channels" item in the TV option row. [CHAR LIMIT=17] -->
@@ -116,54 +114,6 @@
     <!-- Label of "Settings" item in the TV option row. [CHAR LIMIT=17] -->
     <string name="options_item_settings">Settings</string>
 
-    <!-- Label of "Source" item in the PIP option row. The item enables the user to select
-         a specific input (e.g. HDMI 1) for the PIP window. [CHAR LIMIT=17] -->
-    <string name="pip_options_item_source">Source</string>
-    <!-- Label of "Swap" item in the PIP option row.
-         After swapping, the main window and PIP window will show the channels of each other. [CHAR LIMIT=17] -->
-    <string name="pip_options_item_swap">Swap</string>
-    <!-- Description of the "Swap" item in the PIP option row indicating that the currently the
-         windows are swapped. [CHAR LIMIT=20] -->
-    <string name="pip_options_item_swap_on">On</string>
-    <!-- Description of the "Swap" item in the PIP option row indicating that the currently the
-         windows are not swapped. [CHAR LIMIT=20] -->
-    <string name="pip_options_item_swap_off">Off</string>
-    <!-- Label of "Sound" item in the PIP option row. [CHAR LIMIT=17] -->
-    <string name="pip_options_item_sound">Sound</string>
-    <!-- Description of the "Sound" item in the PIP option row indicating that the current sound
-         source is main window. [CHAR LIMIT=20] -->
-    <string name="pip_options_item_sound_main">Main</string>
-    <!-- Description of the "Sound" item in the PIP option row indicating that the current sound
-         source is PIP window. [CHAR LIMIT=20] -->
-    <string name="pip_options_item_sound_pip_window">PIP window</string>
-    <!-- Label of "Layout" item in the PIP option row. [CHAR LIMIT=17] -->
-    <string name="pip_options_item_layout">Layout</string>
-    <!-- Description of the "Layout" item in the PIP option row indicating that the current PIP
-         window is at the bottom right corner of the screen. [CHAR LIMIT=20] -->
-    <string name="pip_options_item_layout_bottom_right">Bottom right</string>
-    <!-- Description of the "Layout" item in the PIP option row indicating that the current PIP
-         window is at the top right corner of the screen. [CHAR LIMIT=20] -->
-    <string name="pip_options_item_layout_top_right">Top right</string>
-    <!-- Description of the "Layout" item in the PIP option row indicating that the current PIP
-         window is at the top left corner of the screen. [CHAR LIMIT=20] -->
-    <string name="pip_options_item_layout_top_left">Top left</string>
-    <!-- Description of the "Layout" item in the PIP option row indicating that the current PIP
-         window is at the bottom left corner of the screen. [CHAR LIMIT=20] -->
-    <string name="pip_options_item_layout_bottom_left">Bottom left</string>
-    <!-- Description of the "Layout" item in the PIP option row indicating that the current PIP
-         layout is side-by-side (i.e. Picture and Picture). [CHAR LIMIT=20] -->
-    <string name="pip_options_item_layout_side_by_side">Side by side</string>
-    <!-- Label of "Size" item in the PIP option row. [CHAR LIMIT=17] -->
-    <string name="pip_options_item_size">Size</string>
-    <!-- Description of the "Size" item in the PIP option row indicating that the current PIP size
-         is big.  [CHAR LIMIT=20] -->
-    <string name="pip_options_item_size_big">Big</string>
-    <!-- Description of the "Size" item in the PIP option row indicating that the current PIP size
-         is small.  [CHAR LIMIT=20] -->
-    <string name="pip_options_item_size_small">Small</string>
-
-    <!-- Title of "Input source" option to select an input for PIP. [CHAR LIMIT=30] -->
-    <string name="side_panel_title_pip_input_source">Input source</string>
     <!-- Label of a unified input for tuner type inputs. [CHAR LIMIT=30] -->
     <string name="input_long_label_for_tuner">TV (antenna/cable)</string>
 
@@ -175,8 +125,11 @@
     <!-- Program title for blocked channel [CHAR LIMIT=23] -->
     <string name="program_title_for_blocked_channel">Blocked channel</string>
 
-    <!-- Default string for unknown language used in "Closed Caption" and "Multi Audio" options. [CHAR LIMIT=30] -->
-    <string name="default_language">Unknown language</string>
+    <!-- Default string for unknown language used in "Multi Audio" options. [CHAR LIMIT=30] -->
+    <string name="multi_audio_unknown_language">Unknown language</string>
+
+    <!-- Default string for unknown language used in "Closed Caption" options. [CHAR LIMIT=30] -->
+    <string name="closed_caption_unknown_language">Closed captions %1$d</string>
 
     <!-- Inside "Closed captions" option side panel -->
     <eat-comment />
@@ -238,6 +191,8 @@
     <eat-comment />
     <!-- Description in the TV guide when the rating of the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
     <string name="program_guide_content_locked">This program is blocked</string>
+    <!-- Description in the TV guide when the current content is unrated and it's restricted by parental control. [CHAR LIMIT=NONE] -->
+    <string name="program_guide_content_locked_unrated">This program is unrated</string>
     <!-- Description in the TV guide with the rating when the rating of the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
     <string name="program_guide_content_locked_format">This program is rated <xliff:g id="rating" example="TV_MA">%1$s</xliff:g></string>
 
@@ -257,11 +212,6 @@
     <!-- Message after no channel is added after setting up an input. [CHAR LIMIT=NONE] -->
     <string name="msg_no_channel_added">No channels added</string>
 
-    <!-- Inside "Input Selector" option side panel -->
-    <eat-comment />
-    <!-- Label of a tuner input in "Input Selector" option. [CHAR LIMIT=30] -->
-    <string name="input_selector_tuner_label">Tuner</string>
-
     <!-- Parental control -->
     <eat-comment />
     <!-- Title of "Parental Contrals" option. [CHAR LIMIT=30] -->
@@ -304,6 +254,12 @@
          [CHAR LIMIT=NONE] -->
     <string name="option_no_enabled_rating_system">None</string>
 
+    <!-- Display name of unrated rating -->
+    <string name="unrated_rating_name">Unrated</string>
+
+    <!-- Label of an item to block unrated programs. [CHAR LIMIT=30] -->
+    <string name="option_block_unrated_programs">Block unrated programs</string>
+
     <!-- Label of an item not to select any restriction. [CHAR LIMIT=30] -->
     <string name="option_rating_none">None</string>
     <!-- Label of an item to select high restriction. [CHAR LIMIT=30] -->
@@ -349,6 +305,9 @@
     <!-- Title of PIN dialog when an user is asked to enter PIN to unlock DVR playback.
          [CHAR LIMIT=NONE] -->
     <string name="pin_enter_unlock_dvr">This program is rated <xliff:g id="rating" example="TV_MA">%1$s</xliff:g>. Enter your PIN to watch this program</string>
+    <!-- Title of PIN dialog when an user is asked to enter PIN to unlock unrated DVR playback.
+         [CHAR LIMIT=NONE] -->
+    <string name="pin_enter_unlock_dvr_unrated">This program is unrated. Enter your PIN to watch this program</string>
     <!-- Title of PIN dialog when an user tries to change Parental control setting.
          [CHAR LIMIT=NONE] -->
     <string name="pin_enter_pin">Enter your PIN</string>
@@ -371,6 +330,15 @@
     <!-- Toast message when an user couldn't pass the PIN confirmation. [CHAR LIMIT=NONE] -->
     <string name="pin_toast_not_match">Try again, PIN doesn\'t match</string>
 
+    <!-- Title of postal/zip code input guided step fragment  [CHAR LIMIT=30] -->
+    <string name="postal_code_guidance_title">Enter your ZIP Code.</string>
+    <!-- Description of postal/zip code input guided step fragment  [CHAR LIMIT=NONE] -->
+    <string name="postal_code_guidance_description">Live TV app will use the ZIP Code to provide a complete program guide for the TV channels.</string>
+    <!-- Description of postal/zip code input edit text view to prompt users entering ZIP Code  [CHAR LIMIT=30] -->
+    <string name="postal_code_action_description">Enter your ZIP Code</string>
+    <!-- Warning message shown in description field of postal/zip code input edit text view when user enters an invalid ZIP Code and presses Done [CHAR LIMIT=30] -->
+    <string name="postal_code_invalid_warning">Invalid ZIP Code</string>
+
     <!-- menu for "Settings" option -->
     <eat-comment />
     <!--  Title of "Settings" option. [CHAR LIMIT=30] -->
@@ -387,10 +355,16 @@
     <string name="settings_channel_source_item_setup_new_inputs">New channels available</string>
     <!-- Label of "Parental controls" item. [CHAR LIMIT=30] -->
     <string name="settings_parental_controls">Parental controls</string>
+    <!-- Label of "Timeshift" item. Record while watching so you can pause or rewind live
+         programs.-->
+    <string name="settings_trickplay">Timeshift</string>
+    <!-- Description of "Timeshift" item. This explains what is 'Timeshift' to users. Also warns of
+         the effect of enabling the option. -->
+    <string name="settings_trickplay_description">Record while watching so you can pause or rewind live programs.\nWarning: This may decrease the life of the internal storage by the intensive use of the storage.</string>
     <!-- Menu item to show licenses for open source code used in the app [CHAR LIMIT=35] -->
     <string name="settings_menu_licenses">Open source licenses</string>
-    <!--Title for a dialog box that shows licenses for open source code used in the app [CHAR LIMIT=35] -->
-    <string name="dialog_title_licenses">Open source licenses</string>
+    <!-- Menu item to send feedback [CHAR LIMIT=30] -->
+    <string name="settings_send_feedback">Send feedback</string>
     <!-- Menu item that shows the application version(eg 1.2.03-final) as a second line below this title [CHAR LIMIT=35] -->
     <string name="settings_menu_version">Version</string>
 
@@ -403,17 +377,23 @@
     <string name="tvview_channel_locked">To watch this channel, press Right and enter your PIN</string>
     <!-- Description on the locked screen when the rating of the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
     <string name="tvview_content_locked">To watch this program, press Right and enter your PIN</string>
+    <!-- Description on the locked screen when the current content is unrated and it's restricted by parental control. [CHAR LIMIT=NONE] -->
+    <string name="tvview_content_locked_unrated">This program is unrated.\nTo watch this program, press Right and enter your PIN</string>
     <!-- Description on the locked screen with the rating when the rating of the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
     <string name="tvview_content_locked_format">This program is rated <xliff:g id="rating" example="TV_MA">%1$s</xliff:g>.\nTo watch this program, press Right and enter your PIN.</string>
     <!-- Description on the locked screen when current channel is locked by parental control. [CHAR LIMIT=NONE] -->
     <string name="tvview_channel_locked_no_permission">To watch this channel, use the default Live TV app.</string>
     <!-- Description on the locked screen when the rating of the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
     <string name="tvview_content_locked_no_permission">To watch this program, use the default Live TV app.</string>
+    <!-- Description on the locked screen when the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
+    <string name="tvview_content_locked_unrated_no_permission">This program is unrated.\nTo watch this program, use the default Live TV app.</string>
     <!-- Description on the locked screen with the rating when the rating of the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
     <string name="tvview_content_locked_format_no_permission">This program is rated <xliff:g id="rating" example="TV_MA">%1$s</xliff:g>.\nTo watch this program, use the default Live TV app.</string>
 
     <!-- Description on the locked screen when the rating of the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
     <string name="shrunken_tvview_content_locked">Program is blocked</string>
+    <!-- Description on the locked screen with the rating when the current content is unrated and it's restricted by parental control. [CHAR LIMIT=NONE] -->
+    <string name="shrunken_tvview_content_locked_unrated">This program is unrated</string>
     <!-- Description on the locked screen with the rating when the rating of the current content is restricted by parental control. [CHAR LIMIT=NONE] -->
     <string name="shrunken_tvview_content_locked_format">This program is rated <xliff:g id="rating" example="TV_MA">%1$s</xliff:g></string>
 
@@ -486,10 +466,6 @@
     <string name="msg_no_input">No TV input found</string>
     <!-- Error message when a specific TV input isn't installed. [CHAR LIMIT=NONE] -->
     <string name="msg_no_specific_input">Cannot find the TV input</string>
-    <!-- Error message when PIP is not supported. [CHAR LIMIT=NONE] -->
-    <string name="msg_no_pip_support">PIP is not supported</string>
-    <!-- Error message when there is no available input. [CHAR LIMIT=NONE] -->
-    <string name="msg_no_available_input_by_pip">There is no available input which can be shown with PIP</string>
     <!-- Error message when the selected TV input is a tuner type TV input, not a pass-through type
          input. Tuner type inputs such as built-in tuner, external usb tuner, network tuner or
          virtual IPTV tuner provide live channels to tune to. As opposed to tuner type input,
@@ -519,22 +495,39 @@
     <!-- Debug Options -->
     <string name="menu_developer_options" translatable="false">Developer options</string>
     <string name="dev_item_watch_history" translatable="false">Watch history</string>
+    <string name="dev_item_dvr_history" translatable="false">DVR history</string>
     <string name="dev_item_fetch_epg" translatable="false">Fetch program guide</string>
-    <string name="dev_item_send_feedback" translatable="false">Send feedback</string>
     <string name="dev_item_store_ts_on" translatable="false">Store TS for debugging: On</string>
     <string name="dev_item_store_ts_off" translatable="false">Store TS for debugging: Off</string>
     <string name="dev_item_store_ts_description" translatable="false">Store some TS data before exceptions/crash for debugging.</string>
+    <string name="dev_item_show_performance_monitor_log" translatable="false">Show performance log</string>
+
+    <!-- The state of the schedules which is in DVR history. -->
+    <string name="dvr_history_dialog_state_fail" translatable="false">[Fail]</string>
+    <string name="dvr_history_dialog_state_success" translatable="false">[Success]</string>
+    <string name="dvr_history_dialog_state_clip" translatable="false">[Clip]</string>
 
     <!-- Title of Recently watched dialog. It is used for debug purpose. -->
     <string name="recently_watched" translatable="false">Recently watched</string>
 
+    <!-- Title of DVR history dialog. -->
+    <string name="dvr_history_dialog_title" translatable="false">DVR history</string>
+
+    <!-- Display name of DVR recording service's notification channel. -->
+    <string name="dvr_notification_channel_name" translatable="false">Live TV DVR</string>
+    <!-- Content title of DVR recording service's notification. -->
+    <string name="dvr_notification_content_title" translatable="false">Live TV DVR</string>
+    <!-- Content text of DVR recording service's notification during recording. -->
+    <string name="dvr_notification_content_text_recording" translatable="false">Live TV are recording.</string>
+    <!-- Content text of DVR recording service's notification during updating schedules. -->
+    <string name="dvr_notification_content_text_loading" translatable="false">Live TV are updating recording schedules.</string>
+
     <!-- EPG Search strings. -->
     <!-- Remove translatable="false" once UI is finalized -->
     <string name="search_result_no_result" translatable="false">No result</string>
     <string name="search_result_title" translatable="false">Search results</string>
 
-    <!-- Onboarding experience.
-         TODO: Change translatable to true.-->
+    <!-- Onboarding experience. -->
     <eat-comment />
     <!-- Text for the channel sources screen in onboarding. -->
     <string name="setup_sources_text">Set up your sources</string>
@@ -542,25 +535,11 @@
     <string name="setup_sources_description">Live channels 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>
 
-    <!-- DVR TODO(DVR): make translatable true. -->
-    <eat-comment />
-    <!-- Dialog message to ask to remove the selected recording schedule. -->
-    <string name="epg_dvr_dialog_message_remove_recording_schedule" translatable="false">Cancel recording</string>
-    <!-- Dialog message to ask to stop the current recording. -->
-    <string name="epg_dvr_dialog_message_stop_recording" translatable="false">Stop recording</string>
-    <!-- Item label to schedule program recording. -->
-    <string name="epg_dvr_record_program" translatable="false">Record program</string>
-    <!-- Item label to schedule whole season recording of a TV show. -->
-    <string name="epg_dvr_record_season" translatable="false">Record season</string>
-    <!-- Item label to delete a recording schedule when a recording scheduled program is
-         clicked in EPG. -->
-    <string name="epg_dvr_delete_program" translatable="false">Delete schedule</string>
-
     <!-- Menu item label to start DVR manager UI. -->
     <string name="channels_item_dvr">Recordings &amp; schedules</string>
     <!-- Menu item label to start recording of the current channel. -->
     <string name="channels_item_record_start" translatable="false">Start recording</string>
-    <!-- Menu item label to start recording of the current channel. -->
+    <!-- Menu item label to stop recording of the current channel. -->
     <string name="channels_item_record_stop" translatable="false">Stop recording</string>
 
     <!-- The action to record the current channel for 10 minutes. [CHAR LIMIT=30] -->
@@ -586,15 +565,10 @@
     <string name="dvr_main_series">Series</string>
     <!-- Header of DVR tab label for recorded programs list without any genre [CHAR LIMIT=20] -->
     <string name="dvr_main_others">Others</string>
-    <string name="dvr_msg_no_recording_on_the_row" translatable="false">None</string>
-    <string name="dvr_msg_channel_unknown" translatable="false">Channel unknown</string>
-    <string name="dvr_msg_no_available_tuners_for_recording_channel" translatable="false">No available tuners to record this channel.</string>
-    <string name="dvr_msg_channel_already_recording" translatable="false">The channel is already being recorded.</string>
     <!-- Toast message that the current channel cannot be recorded. -->
     <string name="dvr_msg_cannot_record_channel">The channel cannot be recorded.</string>
     <!-- Toast message that the current program cannot be recorded. -->
     <string name="dvr_msg_cannot_record_program">The program cannot be recorded.</string>
-    <string name="dvr_msg_no_item_in_browse" translatable="false">There is no item.</string>
     <!-- Toast message that a new recording schedule has been created from the user action. -->
     <string name="dvr_msg_program_scheduled"><xliff:g id="programName" example="Big bang theory">%1$s</xliff:g> has been scheduled to be recorded</string>
     <!-- Toast message that a new recording schedule of the current program has been created
@@ -631,9 +605,10 @@
 
     <!-- DVR detailed page -->
     <eat-comment />
-    <string name="dvr_detail_cancel" translatable="false">Cancel recording</string>
-    <string name="dvr_detail_stop_keep" translatable="false">Stop and keep recording</string>
-    <string name="dvr_detail_stop_delete" translatable="false">Stop and delete recording</string>
+    <!-- Button label to cancel the recording schedule. -->
+    <string name="dvr_detail_cancel_recording">Cancel recording</string>
+    <!-- Button label to stop the current recording. -->
+    <string name="dvr_detail_stop_recording">Stop recording</string>
     <!-- Button label to play recorded programs from beginning.
          Displayed when there's no watched history available. [CHAR LIMIT=15] -->
     <string name="dvr_detail_watch">Watch</string>
@@ -655,6 +630,7 @@
     <!-- Text label to indicate there's more text in the details description [CHAR LIMIT=20] -->
     <string name="dvr_detail_read_more">Read more</string>
 
+
     <!-- DVR series settings -->
     <eat-comment />
     <!-- Title of DVR series deletion [CHAR LIMIT=25] -->
@@ -709,18 +685,10 @@
 
     <!-- DVR epg strings -->
     <eat-comment />
-    <string name="dvr_action_tune" translatable="false">Tune</string>
-    <!-- The action to cancel and close the dialog. [CHAR LIMIT=10] -->
-    <string name="dvr_action_cancel">Cancel</string>
     <string name="dvr_action_delete_schedule" translatable="false">Delete schedule</string>
     <string name="dvr_action_record_program" translatable="false">Record program</string>
-    <string name="dvr_action_record_one_episode" translatable="false">Record this episode only</string>
-    <string name="dvr_action_error_done" translatable="false">Done</string>
-    <string name="dvr_action_error_open_dvr" translatable="false">Open DVR</string>
-    <!-- The action to cancel forgetting DVR storage. -->
-    <string name="dvr_action_error_cancel">Cancel</string>
-    <!-- The action to forget DVR storage which is missing currently -->
-    <string name="dvr_action_error_forget_storage">Forget</string>
+    <!-- The action to forget DVR storage which is missing currently. invoke android internal storage settings activity. -->
+    <string name="dvr_action_error_storage_settings" translatable="false">Open storage settings</string>
     <!-- The action to stop recording. [CHAR LIMIT=10] -->
     <string name="dvr_action_stop">Stop</string>
     <!-- The action to open the activity which shows all the schedules.[CHAR LIMIT=32] -->
@@ -749,6 +717,8 @@
     <string name="dvr_action_record_cancel">Cancel this recording</string>
     <!-- The title of the action to show the details of the recorded program. [CHAR LIMIT=32] -->
     <string name="dvr_action_watch_now">Watch now</string>
+    <!-- The title of the action to open the DVR library to delete some recorded programs. [CHAR LIMIT=32] -->
+    <string name="dvr_action_delete_recordings">Delete recordings&#8230;</string>
     <!-- Dvr label in epg to indicate the program is recordable. [CHAR LIMIT=30] -->
     <string name="dvr_epg_program_recordable">Recordable</string>
     <!-- Dvr label in epg to indicate the program is scheduled to be recorded. [CHAR LIMIT=30] -->
@@ -762,28 +732,37 @@
     <string name="dvr_epg_program_icon_text" translatable="false">DVR</string>
     <string name="dvr_epg_channel_watch_conflict_dialog_title" translatable="false">Upcoming schedules</string>
     <string name="dvr_epg_channel_watch_conflict_dialog_description" translatable="false">The programs will not be recorded if you keep watching this channel. Cancel the recordings, or current channel will be blocked when the recording starts.</string>
-    <!-- A popup message which informs that Live TV is reading program information to create
-         recording schedules. -->
-    <string name="dvr_schedule_progress_message_reading_programs">Reading programs to create recording schedules</string>
     <!-- A popup message which informs that Live TV is reading program information. -->
-    <string name="dvr_series_schedules_progress_message_reading_programs">Reading programs</string>
-    <!-- A popup message which informs that Live TV is updating series recording. -->
-    <string name="dvr_series_schedules_progress_message_updating_programs">Updating series recording</string>
-    <string name="dvr_error_insufficient_space_title" translatable="false">Insufficient storage space</string>
-    <string name="dvr_error_insufficient_space_description" translatable="false">No sufficient storage space for recording. Please clean up the storage.</string>
+    <string name="dvr_series_progress_message_reading_programs">Reading programs</string>
+    <!-- Dialog action which let user view the recent recordings. -->
+    <string name="dvr_error_insufficient_space_action_view_recent_recordings">View recent recordings</string>
+    <!-- Dialog title which means there is one recording doesn't complete. -->
+    <string name="dvr_error_insufficient_space_title_one_recording">The recording of <xliff:g id="programName" example="Friends">%1$s</xliff:g> is incomplete.</string>
+    <!-- Dialog title which means there are two recordings don't complete. -->
+    <string name="dvr_error_insufficient_space_title_two_recordings">The recordings of <xliff:g id="programName_1" example="Friends">%1$s</xliff:g> and <xliff:g id="programName_2" example="Friends">%2$s</xliff:g> are incomplete.</string>
+    <!-- Dialog title which means there are three or more recordings don't complete.-->
+    <string name="dvr_error_insufficient_space_title_three_or_more_recordings">The recordings of <xliff:g id="programName_1" example="Friends">%1$s</xliff:g>, <xliff:g id="programName_2" example="Friends">%2$s</xliff:g> and <xliff:g id="programName_3" example="Friends">%3$s</xliff:g> are incomplete.</string>
+    <!-- Description which means there is one recording didn't complete due to no sufficient space.
+         -->
+    <string name="dvr_error_insufficient_space_description_one_recording">The recording of <xliff:g id="programName" example="Friends">%1$s</xliff:g> didn\'t complete due to insufficient storage.</string>
+    <!-- Description which means there are two recordings didn't complete due to no sufficient
+         space. -->
+    <string name="dvr_error_insufficient_space_description_two_recordings">The recordings of <xliff:g id="programName_1" example="Friends">%1$s</xliff:g> and <xliff:g id="programName_2" example="Friends">%2$s</xliff:g> didn\'t complete due to insufficient storage.</string>
+    <!-- Description which means there are three or more recordings didn't complete due to no
+         sufficient space.-->
+    <string name="dvr_error_insufficient_space_description_three_or_more_recordings">The recordings of <xliff:g id="programName_1" example="Friends">%1$s</xliff:g>, <xliff:g id="programName_2" example="Friends">%2$s</xliff:g> and <xliff:g id="programName_3" example="Friends">%3$s</xliff:g> didn\'t complete due to insufficient storage.</string>
     <!-- Dialog title which will be shown when the current storage is too small for DVR. -->
     <string name="dvr_error_small_sized_storage_title">DVR needs more storage</string>
-    <!-- Dialog description which will be shown when tthe current storage is too small for DVR. -->
-    <string name="dvr_error_small_sized_storage_description">You will be able to record programs with DVR. However there is not enough storage on your device now for DVR to work. Please connect an external drive that is <xliff:g id="storage size" example="10GB">%1$s</xliff:g>GB or larger and follow the steps to format it as device storage.</string>
+    <!-- Dialog description which will be shown when the current storage is too small for DVR. -->
+    <string name="dvr_error_small_sized_storage_description">You will be able to record programs with DVR. However there is not enough storage on your device now for DVR to work. Please connect an external drive that is <xliff:g id="storage size" example="10GB">%1$d</xliff:g>GB or larger and follow the steps to format it as device storage.</string>
+    <!-- Dialog title which will be shown when there is no free space on the current storage for DVR. -->
+    <string name="dvr_error_no_free_space_title">Not enough storage</string>
+    <!-- Dialog description which will be shown when there is no free space on the current storage for DVR. -->
+    <string name="dvr_error_no_free_space_description">This program will not be recorded because there is not enough storage. Try deleting some existing recordings.</string>
     <!-- Dialog title which will be shown when the current DVR storage is not accessible. -->
     <string name="dvr_error_missing_storage_title">Missing storage</string>
     <!-- Dialog description which will be shown when the current DVR storage is not accessible. -->
-    <string name="dvr_error_missing_storage_description">Some of the storage used by DVR is missing. Please connect the external drive you used before to re-enable DVR. Alternately, you can choose to forget the storage if it\'s no longer available.</string>
-    <!-- Dialog title which will be shown when you confirmed to forget the current DVR storage. -->
-    <string name="dvr_error_forget_storage_title">Forget storage?</string>
-    <!-- Dialog description which will be shown when you confirmed to forget the current DVR
-         storage. -->
-    <string name="dvr_error_forget_storage_description">All your recorded content and schedules will be lost.</string>
+    <string name="dvr_error_missing_storage_description" translatable="false">Some of the storage used by DVR is missing. Please connect the external drive you used before to re-enable DVR. Alternately, you can forget the storage in the storage settings, if it\'s no longer available.</string>
     <!-- The recording being requested to play is not existent in storage. It may be deleted. -->
     <string name="dvr_toast_recording_deleted" translatable="false">The recording seems to be deleted.</string>
 
@@ -847,66 +826,53 @@
     <string name="dvr_already_recorded_dialog_description">This program has already been recorded. It’s available in the DVR library.</string>
     <!-- The title of dialog that notifies the user the series recording has been scheduled. -->
     <string name="dvr_series_recording_dialog_title">Series recording scheduled</string>
-    <!-- The description of the dialog which notifies how many schedules has been added
-         for series recording.-->
-    <plurals name="dvr_series_recording_scheduled_no_conflict">
-        <item quantity="one">%1$d recording has been scheduled for %2$s.</item>
-        <item quantity="other">%1$d recordings have been scheduled for %2$s.</item>
+    <!-- The description of the dialog which notifies how many schedules have been added for the
+         series. -->
+    <plurals name="dvr_series_scheduled_no_conflict">
+        <item quantity="one"><xliff:g id="numberOfRecordings" example="1">%1$d</xliff:g> recording has been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>.</item>
+        <item quantity="other"><xliff:g id="numberOfRecordings" example="5">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>.</item>
     </plurals>
-    <!-- The description of the dialog which notifies how many schedules has been added
-         for series recording. But some of them won't be recorded due to conflicts. -->
+    <!-- The description of the dialog which notifies how many schedules have been added for the
+         series. But some episodes of this series won't be recorded due to conflict with
+         other schedules. -->
     <plurals name="dvr_series_recording_scheduled_only_this_series_conflict">
-        <item quantity="one">%1$d recording has been scheduled for %2$s. %3$d of them will not be recorded due to conflicts.</item>
-        <item quantity="other">%1$d recordings have been scheduled for %2$s. %3$d of them will not be recorded due to conflicts.</item>
+        <item quantity="one"><xliff:g id="numberOfRecordings" example="1">%1$d</xliff:g> recording has been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>. It will not be recorded due to conflicts.</item>
+        <item quantity="other"><xliff:g id="numberOfRecordings" example="5">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>. <xliff:g id="numberOfConflictRecordings" example="2">%3$d</xliff:g> of them will not be recorded due to conflicts.</item>
     </plurals>
-    <!-- The description of the dialog which notifies how many schedules has been added
-         for series recording. But only 1 episode of other series won't be recorded due to conflict
+    <!-- The description of the dialog which notifies how many schedules have been added for the
+         series. But some episodes of this and other series won't be recorded due to the episodes
+         of this series conflict with other schedules and the episodes of other series conflict
          with this series. -->
-    <plurals name="dvr_series_recording_scheduled_this_and_other_series_one_conflict">
-        <item quantity="one">%1$d recording has been scheduled for %2$s. 1 episode of this series and other series will not be recorded due to conflicts.</item>
-        <item quantity="other">%1$d recordings have been scheduled for %2$s. 1 episode of this series and other series will not be recorded due to conflicts.</item>
+    <plurals name="dvr_series_scheduled_this_and_other_series_conflict">
+        <item quantity="one"><xliff:g id="numberOfRecordings" example="1">%1$d</xliff:g> recording has been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>. <xliff:g id="numberOfConflictEpisodes" example="1">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
+        <item quantity="other"><xliff:g id="numberOfRecordings" example="5">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>. <xliff:g id="numberOfConflictEpisodes" example="2">%3$d</xliff:g> episodes of this series and other series will not be recorded due to conflicts.</item>
     </plurals>
-    <!-- The description of the dialog which notifies how many schedules has been added
-        for series recording. But some episodes of other series won't be recorded due to conflict
-        with this. -->
-    <plurals name="dvr_series_recording_scheduled_this_and_other_series_conflict">
-        <item quantity="one">%1$d recording has been scheduled for %2$s. %3$d episodes of this series and other series will not be recorded due to conflicts.</item>
-        <item quantity="other">%1$d recordings have been scheduled for %2$s. %3$d episodes of this series and other series will not be recorded due to conflicts.</item>
+    <!-- The description of the dialog which notifies how many schedules have been added for the
+         series. But only 1 episode of other series won't be recorded due to conflict
+         with this series. -->
+    <plurals name="dvr_series_scheduled_only_other_series_one_conflict">
+        <item quantity="one"><xliff:g id="numberOfRecordings" example="1">%1$d</xliff:g> recording has been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
+        <item quantity="other"><xliff:g id="numberOfRecordings" example="5">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>. 1 episode of other series will not be recorded due to conflicts.</item>
     </plurals>
-    <!-- The description of the dialog which notifies how many schedules has been added
-        for series recording. But only 1 episode of other series won't be recorded due to conflict
-        with this series but no conflicts in this series. -->
-    <plurals name="dvr_series_recording_scheduled_only_other_series_one_conflict">
-        <item quantity="one">%1$d recording has been scheduled for %2$s. 1 episode of other series will not be recorded due to conflicts.</item>
-        <item quantity="other">%1$d recordings have been scheduled for %2$s. 1 episode of other series will not be recorded due to conflicts.</item>
-    </plurals>
-    <!-- The description of the dialog which notifies how many schedules has been added
-      for series recording. But some of other series won't be recorded due to conflict with this
-      series but no conflicts in this series . -->
-    <plurals name="dvr_series_recording_scheduled_only_other_series_conflict">
-        <item quantity="one">%1$d recording has been scheduled for %2$s. %3$d episodes of other series will not be recorded due to conflicts.</item>
-        <item quantity="other">%1$d recordings have been scheduled for %2$s. %3$d episodes of other series will not be recorded due to conflicts.</item>
+    <!-- The description of the dialog which notifies how many schedules have been added for the
+         series. But some episodes of other series won't be recorded due to conflict with this
+         series. -->
+    <plurals name="dvr_series_scheduled_only_other_series_many_conflicts">
+        <item quantity="one"><xliff:g id="numberOfRecordings" example="1">%1$d</xliff:g> recording has been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>. <xliff:g id="numberOfConflictEpisodes" example="1">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
+        <item quantity="other"><xliff:g id="numberOfRecordings" example="5">%1$d</xliff:g> recordings have been scheduled for <xliff:g id="seriesName" example="Friends">%2$s</xliff:g>. <xliff:g id="numberOfConflictEpisodes" example="2">%3$d</xliff:g> episodes of other series will not be recorded due to conflicts.</item>
     </plurals>
 
     <!-- DVR playback strings -->
     <eat-comment />
-    <string name="dvr_now_playing_card_no_title" translatable="false">Recorded Program</string>
     <!-- DVR playback activity's warning about the recorded program is not found. -->
     <string name="dvr_program_not_found">Recorded program not found.</string>
     <!-- Label used in DVR playback activity as the header of the row of related recordings. [CHAR LIMIT=32] -->
     <string name="dvr_playback_related_recordings">Related recordings</string>
-    <!-- Label used in related recording cards to indicate that the program does not have descriptions. [CHAR LIMIT=32] -->
-    <string name="dvr_msg_no_program_description">(No program description)</string>
 
     <!-- DVR channel banner strings -->
     <eat-comment />
     <string name="dvr_recording_till_format" translatable="false">Recording till <xliff:g id="recordingEndTime" example="9:00pm">%1$s</xliff:g></string>
 
-    <!-- Account Selection strings -->
-    <eat-comment />
-    <string name="account_selected" translatable="false">%1$s is the selected account</string>
-    <string name="no_account_selected" translatable="false">No account available</string>
-
     <!-- DVR schedule list strings -->
     <eat-comment/>
     <!-- Description of list's header about how many recordings in the recording list. -->
@@ -944,6 +910,8 @@
     <string name="dvr_series_schedules_stop_dialog_description">Recorded episodes will remain available in the DVR library.</string>
     <!-- Action to stop creating the schedules for the series. -->
     <string name="dvr_series_schedules_stop_dialog_action_stop">Stop</string>
+     <!-- Description of no episodes in stopped series recording. -->
+    <string name="dvr_series_schedules_stopped_empty_state">No episodes are on air now.</string>
     <!-- Description of no episodes in series recording, and the episodes will be recorded once
          they are available. -->
     <string name="dvr_series_schedules_empty_state">No episodes are available.\nThey will be recorded once they are available.</string>
@@ -974,4 +942,9 @@
     <eat-comment/>
     <!-- Text that goes after a Critic Score to indicate that it's a score -->
     <string name="program_guide_critic_score">Score</string>
+
+    <!-- Preview Channel Name -->
+    <eat-comment/>
+    <!-- Name for recorded programs preview channel -->
+    <string name="recorded_programs_preview_channel">Recorded Programs</string>
 </resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 3a34af5..84885f1 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -92,7 +92,7 @@
         <item name="android:textSize">14sp</item>
         <item name="android:textColor">@color/lb_basic_card_title_text_color</item>
         <item name="android:fontFamily">sans-serif-condensed</item>
-        <item name="android:singleLine">true</item>
+        <item name="android:maxLines">@integer/dvr_card_title_max_lines_folded</item>
         <item name="android:ellipsize">end</item>
     </style>
 
@@ -143,7 +143,7 @@
         <item name="android:layout_height">60dp</item>
     </style>
 
-    <style name="TV.Dvr.GuidedActionsListStyle" parent="Widget.Setup.GuidedActionsListStyle">
+    <style name="TV.Dvr.GuidedActionsListStyle" parent="Widget.Leanback.GuidedActionsListStyle">
         <item name="android:layout_marginTop">51dp</item>
         <item name="android:layout_marginBottom">10dp</item>
         <item name="android:layout_marginEnd">56dp</item>
@@ -151,11 +151,8 @@
 
     <style name="TV.Dvr.GuidedActionItemContainerStyle" parent="Widget.Setup.GuidedActionItemContainerStyle">
         <item name="android:layout_height">48dp</item>
-        <item name="android:layout_marginTop">7dp</item>
-        <item name="android:paddingBottom">15dp</item>
         <item name="android:paddingEnd">16dp</item>
         <item name="android:paddingStart">16dp</item>
-        <item name="android:paddingTop">14dp</item>
     </style>
 
     <style name="TV.Dvr.GuidedActionItemContainerStyle.Twoline.Action" parent="TV.Dvr.GuidedActionItemContainerStyle">
diff --git a/res/values/themes.xml b/res/values/themes.xml
index 9be64eb..2165a75 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -114,5 +114,10 @@
 
     <style name="Theme.TV.Dvr.Browse.Details" parent="Theme.Leanback.Details">
         <item name="detailsDescriptionTitleStyle">@style/TV.Dvr.Browse.DetailsDescriptionTitleStyle</item>
+        <item name="android:windowSharedElementEnterTransition">@transition/dvr_details_shared_element_enter_transition</item>
+        <item name="android:windowSharedElementReturnTransition">@transition/dvr_details_shared_element_return_transition</item>
+        <!-- Disallows transition overlapping to prevent jankiness caused by ripple effects of
+             clicking DVR cards overlapping with fragment transition. -->
+        <item name="android:windowAllowEnterTransitionOverlap">false</item>
     </style>
-</resources>
+</resources>
\ No newline at end of file
diff --git a/res/xml/remote_config_defaults.xml b/res/xml/remote_config_defaults.xml
index 742bff2..6ecad19 100644
--- a/res/xml/remote_config_defaults.xml
+++ b/res/xml/remote_config_defaults.xml
@@ -16,7 +16,22 @@
   -->
 <defaultsMap>
     <entry>
+        <key>live_channels_ac3_software_decoder</key>
+        <value>false</value>
+    </entry>
+
+    <entry>
         <key>live_channels_epg_host_and_port</key>
         <value>datamixer-pa.googleapis.com:443</value>
     </entry>
+
+    <entry>
+        <key>live_channels_epg_fetcher_interval_hour</key>
+        <value>4</value>
+    </entry>
+
+    <entry>
+        <key>live_channels_epg_reader_max_channels_per_program_fetch</key>
+        <value>20</value>
+    </entry>
 </defaultsMap>
\ No newline at end of file
diff --git a/src/com/android/exoplayer/text/SubtitleView.java b/src/com/android/exoplayer/text/SubtitleView.java
index b1161f2..37926ed 100644
--- a/src/com/android/exoplayer/text/SubtitleView.java
+++ b/src/com/android/exoplayer/text/SubtitleView.java
@@ -39,14 +39,12 @@
 
 /**
  * Since this class does not exist in recent version of ExoPlayer and used by
- * {@link com.google.android.tv.tuner.cc.CaptionWindowLayout}, this class is copied from
+ * {@link com.android.tv.tuner.cc.CaptionWindowLayout}, this class is copied from
  * older version of ExoPlayer.
  * A view for rendering a single caption.
  */
 @Deprecated
 public class SubtitleView extends View {
-    // TODO: Change usage of this class to up-to-date class of ExoPlayer.
-
     /**
      * Ratio of inner padding to font size.
      */
diff --git a/src/com/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java b/src/com/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java
new file mode 100644
index 0000000..2b7817d
--- /dev/null
+++ b/src/com/android/exoplayer2/ext/ffmpeg/FfmpegAudioDecoder.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2017 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.google.android.exoplayer2.ext.ffmpeg;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
+import com.google.android.exoplayer2.decoder.SimpleOutputBuffer;
+import com.google.android.exoplayer2.util.MimeTypes;
+import com.android.tv.common.SoftPreconditions;
+
+import java.nio.ByteBuffer;
+
+/**
+ * Audio decoder which uses ffmpeg extension of ExoPlayer2. Since {@link FfmpegDecoder} is package
+ * private, expose the decoder via this class. Supported formats are AC3 and MP2.
+ */
+public class FfmpegAudioDecoder {
+    private static final int NUM_DECODER_BUFFERS = 1;
+
+    // The largest AC3 sample size. This is bigger than the largest MP2 sample size (1729).
+    private static final int INITIAL_INPUT_BUFFER_SIZE = 2560;
+    private static boolean AVAILABLE;
+
+    static {
+        AVAILABLE =
+                FfmpegLibrary.supportsFormat(MimeTypes.AUDIO_AC3)
+                        && FfmpegLibrary.supportsFormat(MimeTypes.AUDIO_MPEG_L2);
+    }
+
+    private FfmpegDecoder mDecoder;
+    private DecoderInputBuffer mInputBuffer;
+    private SimpleOutputBuffer mOutputBuffer;
+    private boolean mStarted;
+
+    /** Return whether Ffmpeg based software audio decoder is available. */
+    public static boolean isAvailable() {
+        return AVAILABLE;
+    }
+
+    /** Creates an Ffmpeg based software audio decoder. */
+    public FfmpegAudioDecoder(Context context) {
+        if (context.checkSelfPermission("android.permission.INTERNET")
+                == PackageManager.PERMISSION_GRANTED) {
+            throw new IllegalStateException("This code should run in an isolated process");
+        }
+    }
+
+    /**
+     * Decodes an audio sample.
+     *
+     * @param timeUs presentation timestamp of the sample
+     * @param sample data
+     */
+    public void decode(long timeUs, byte[] sample) {
+        SoftPreconditions.checkState(AVAILABLE);
+        mInputBuffer.data.clear();
+        mInputBuffer.data.put(sample);
+        mInputBuffer.data.flip();
+        mInputBuffer.timeUs = timeUs;
+        mDecoder.decode(mInputBuffer, mOutputBuffer, !mStarted);
+        if (!mStarted) {
+            mStarted = true;
+        }
+    }
+
+    /** Returns a decoded sample from decoder. */
+    public ByteBuffer getDecodedSample() {
+        return mOutputBuffer.data;
+    }
+
+    /** Returns the presentation time for the decoded sample. */
+    public long getDecodedTimeUs() {
+        return mOutputBuffer.timeUs;
+    }
+
+    /**
+     * Clear previous decode state if any. Prepares to decode samples of the specified encoding.
+     * This method should be called before using decode.
+     *
+     * @param mime audio encoding
+     */
+    public void resetDecoderState(String mime) {
+        SoftPreconditions.checkState(AVAILABLE);
+        release();
+        try {
+            mDecoder =
+                    new FfmpegDecoder(
+                            NUM_DECODER_BUFFERS,
+                            NUM_DECODER_BUFFERS,
+                            INITIAL_INPUT_BUFFER_SIZE,
+                            mime,
+                            null);
+            mStarted = false;
+            mInputBuffer = mDecoder.createInputBuffer();
+            // Since native JNI requires direct buffer, we should allocate it by #allocateDirect.
+            mInputBuffer.data = ByteBuffer.allocateDirect(INITIAL_INPUT_BUFFER_SIZE);
+            mOutputBuffer = mDecoder.createOutputBuffer();
+        } catch (FfmpegDecoderException e) {
+            // if AVAILABLE is {@code true}, this will not happen.
+        }
+    }
+
+    /** Releases all the resource. */
+    public void release() {
+        SoftPreconditions.checkState(AVAILABLE);
+        if (mDecoder != null) {
+            mDecoder.release();
+            mInputBuffer = null;
+            mOutputBuffer = null;
+            mDecoder = null;
+        }
+    }
+}
diff --git a/src/com/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java b/src/com/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java
new file mode 100644
index 0000000..daa7734
--- /dev/null
+++ b/src/com/android/exoplayer2/ext/ffmpeg/FfmpegLibrary.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2017 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.google.android.exoplayer2.ext.ffmpeg;
+
+import com.google.android.exoplayer2.util.LibraryLoader;
+import com.google.android.exoplayer2.util.MimeTypes;
+
+/**
+ * This class is based on com.google.android.exoplayer2.ext.ffmpeg.FfmpegLibrary from ExoPlayer2
+ * in order to support mp2 decoder.
+ * Configures and queries the underlying native library.
+ */
+public final class FfmpegLibrary {
+
+    private static final LibraryLoader LOADER =
+            new LibraryLoader("avutil", "avresample", "avcodec", "ffmpeg");
+
+    private FfmpegLibrary() {}
+
+    /**
+     * Overrides the names of the FFmpeg native libraries. If an application wishes to call this
+     * method, it must do so before calling any other method defined by this class, and before
+     * instantiating a {@link FfmpegAudioRenderer} instance.
+     */
+    public static void setLibraries(String... libraries) {
+        LOADER.setLibraries(libraries);
+    }
+
+    /**
+     * Returns whether the underlying library is available, loading it if necessary.
+     */
+    public static boolean isAvailable() {
+        return LOADER.isAvailable();
+    }
+
+    /**
+     * Returns the version of the underlying library if available, or null otherwise.
+     */
+    public static String getVersion() {
+        return isAvailable() ? ffmpegGetVersion() : null;
+    }
+
+    /**
+     * Returns whether the underlying library supports the specified MIME type.
+     */
+    public static boolean supportsFormat(String mimeType) {
+        if (!isAvailable()) {
+            return false;
+        }
+        String codecName = getCodecName(mimeType);
+        return codecName != null && ffmpegHasDecoder(codecName);
+    }
+
+    /**
+     * Returns the name of the FFmpeg decoder that could be used to decode {@code mimeType}.
+     */
+    /* package */ static String getCodecName(String mimeType) {
+        switch (mimeType) {
+            case MimeTypes.AUDIO_MPEG_L2:
+                return "mp2";
+            case MimeTypes.AUDIO_AC3:
+                return "ac3";
+            default:
+                return null;
+        }
+    }
+
+    private static native String ffmpegGetVersion();
+    private static native boolean ffmpegHasDecoder(String codecName);
+
+}
diff --git a/src/com/android/tv/ApplicationSingletons.java b/src/com/android/tv/ApplicationSingletons.java
index fd125d5..ac7d4c4 100644
--- a/src/com/android/tv/ApplicationSingletons.java
+++ b/src/com/android/tv/ApplicationSingletons.java
@@ -20,12 +20,15 @@
 import com.android.tv.analytics.Tracker;
 import com.android.tv.config.RemoteConfig;
 import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.PreviewDataManager;
 import com.android.tv.data.ProgramDataManager;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.DvrScheduleManager;
 import com.android.tv.dvr.DvrStorageStatusManager;
 import com.android.tv.dvr.DvrWatchedPositionManager;
+import com.android.tv.dvr.recorder.RecordingScheduler;
+import com.android.tv.perf.PerformanceMonitor;
 import com.android.tv.util.AccountHelper;
 import com.android.tv.util.TvInputManagerHelper;
 
@@ -38,6 +41,22 @@
 
     ChannelDataManager getChannelDataManager();
 
+    /**
+     * Checks if the {@link ChannelDataManager} instance has been created and all the channels has
+     * been loaded.
+     */
+    boolean isChannelDataManagerLoadFinished();
+
+    ProgramDataManager getProgramDataManager();
+
+    /**
+     * Checks if the {@link ProgramDataManager} instance has been created and the current programs
+     * for all the channels has been loaded.
+     */
+    boolean isProgramDataManagerCurrentProgramsLoadFinished();
+
+    PreviewDataManager getPreviewDataManager();
+
     DvrDataManager getDvrDataManager();
 
     DvrStorageStatusManager getDvrStorageStatusManager();
@@ -46,12 +65,12 @@
 
     DvrManager getDvrManager();
 
+    RecordingScheduler getRecordingScheduler();
+
     DvrWatchedPositionManager getDvrWatchedPositionManager();
 
     InputSessionManager getInputSessionManager();
 
-    ProgramDataManager getProgramDataManager();
-
     Tracker getTracker();
 
     TvInputManagerHelper getTvInputManagerHelper();
@@ -61,4 +80,8 @@
     AccountHelper getAccountHelper();
 
     RemoteConfig getRemoteConfig();
+
+    boolean isRunningInMainProcess();
+
+    PerformanceMonitor getPerformanceMonitor();
 }
diff --git a/src/com/android/tv/AudioManagerHelper.java b/src/com/android/tv/AudioManagerHelper.java
new file mode 100644
index 0000000..4fca06a
--- /dev/null
+++ b/src/com/android/tv/AudioManagerHelper.java
@@ -0,0 +1,108 @@
+package com.android.tv;
+
+import android.app.Activity;
+import android.content.Context;
+import android.media.AudioManager;
+import android.os.Build;
+
+import com.android.tv.receiver.AudioCapabilitiesReceiver;
+import com.android.tv.ui.TunableTvView;
+
+/**
+ * A helper class to help {@link MainActivity} to handle audio-related stuffs.
+ */
+class AudioManagerHelper implements AudioManager.OnAudioFocusChangeListener {
+    private static final float AUDIO_MAX_VOLUME = 1.0f;
+    private static final float AUDIO_MIN_VOLUME = 0.0f;
+    private static final float AUDIO_DUCKING_VOLUME = 0.3f;
+
+    private final Activity mActivity;
+    private final TunableTvView mTvView;
+    private final AudioManager mAudioManager;
+    private final AudioCapabilitiesReceiver mAudioCapabilitiesReceiver;
+
+    private boolean mAc3PassthroughSupported;
+    private int mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
+
+    AudioManagerHelper(Activity activity, TunableTvView tvView) {
+        mActivity = activity;
+        mTvView = tvView;
+        mAudioManager = (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
+        mAudioCapabilitiesReceiver = new AudioCapabilitiesReceiver(activity,
+                new AudioCapabilitiesReceiver.OnAc3PassthroughCapabilityChangeListener() {
+                    @Override
+                    public void onAc3PassthroughCapabilityChange(boolean capability) {
+                        mAc3PassthroughSupported = capability;
+                    }
+                });
+        mAudioCapabilitiesReceiver.register();
+    }
+
+    /**
+     * Sets suitable volume to {@link TunableTvView} according to the current audio focus.
+     * If the focus status is {@link AudioManager#AUDIOFOCUS_LOSS} and the activity is under PIP
+     * mode, this method will finish the activity.
+     */
+    void setVolumeByAudioFocusStatus() {
+        if (mTvView.isPlaying()) {
+            switch (mAudioFocusStatus) {
+                case AudioManager.AUDIOFOCUS_GAIN:
+                    mTvView.setStreamVolume(AUDIO_MAX_VOLUME);
+                    break;
+                case AudioManager.AUDIOFOCUS_LOSS:
+                    if (Features.PICTURE_IN_PICTURE.isEnabled(mActivity)
+                            && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+                            && mActivity.isInPictureInPictureMode()) {
+                        mActivity.finish();
+                        break;
+                    }
+                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
+                    mTvView.setStreamVolume(AUDIO_MIN_VOLUME);
+                    break;
+                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
+                    mTvView.setStreamVolume(AUDIO_DUCKING_VOLUME);
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Tries to request audio focus from {@link AudioManager} and set volume according to the
+     * returned result.
+     */
+    void requestAudioFocus() {
+        int result = mAudioManager.requestAudioFocus(this,
+                AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
+        mAudioFocusStatus = (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) ?
+                AudioManager.AUDIOFOCUS_GAIN : AudioManager.AUDIOFOCUS_LOSS;
+        setVolumeByAudioFocusStatus();
+    }
+
+    /**
+     * Abandons audio focus.
+     */
+    void abandonAudioFocus() {
+        mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
+        mAudioManager.abandonAudioFocus(this);
+    }
+
+    /**
+     * Returns {@code true} if the device supports AC3 pass-through.
+     */
+    boolean isAc3PassthroughSupported() {
+        return mAc3PassthroughSupported;
+    }
+
+    /**
+     * Release the resources the helper class may occupied.
+     */
+    void release() {
+        mAudioCapabilitiesReceiver.unregister();
+    }
+
+    @Override
+    public void onAudioFocusChange(int focusChange) {
+        mAudioFocusStatus = focusChange;
+        setVolumeByAudioFocusStatus();
+    }
+}
diff --git a/src/com/android/tv/Features.java b/src/com/android/tv/Features.java
index 7e8e368..2052f2e 100644
--- a/src/com/android/tv/Features.java
+++ b/src/com/android/tv/Features.java
@@ -16,29 +16,39 @@
 
 package com.android.tv;
 
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.tv.common.feature.Feature;
+import com.android.tv.common.feature.GServiceFeature;
+import com.android.tv.common.feature.PropertyFeature;
+import com.android.tv.config.RemoteConfig;
+import com.android.tv.experiments.Experiments;
+import com.android.tv.util.LocationUtils;
+import com.android.tv.util.PermissionUtils;
+import com.android.tv.util.Utils;
+
+import java.util.Locale;
+
 import static com.android.tv.common.feature.EngOnlyFeature.ENG_ONLY_FEATURE;
 import static com.android.tv.common.feature.FeatureUtils.AND;
 import static com.android.tv.common.feature.FeatureUtils.OFF;
 import static com.android.tv.common.feature.FeatureUtils.ON;
 import static com.android.tv.common.feature.FeatureUtils.OR;
 
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.support.annotation.VisibleForTesting;
-import android.support.v4.os.BuildCompat;
-
-import com.android.tv.common.feature.Feature;
-import com.android.tv.common.feature.GServiceFeature;
-import com.android.tv.common.feature.PropertyFeature;
-import com.android.tv.util.PermissionUtils;
-
 /**
  * List of {@link Feature} for the Live TV App.
  *
  * <p>Remove the {@code Feature} once it is launched.
  */
 public final class Features {
+    private static final String TAG = "Features";
+    private static final boolean DEBUG = false;
+
     /**
      * UI for opting in to analytics.
      *
@@ -57,17 +67,40 @@
     public static final Feature EPG_SEARCH =
             new PropertyFeature("feature_tv_use_epg_search", false);
 
-    public static final Feature TUNER = new Feature() {
-        @Override
-        public boolean isEnabled(Context context) {
+    public static final Feature TUNER =
+            new Feature() {
+                @Override
+                public boolean isEnabled(Context context) {
 
-            // This is special handling just for USB Tuner.
-            // It does not require any N API's but relies on a improvements in N for AC3 support
-            // After release, change class to this to just be {@link BuildCompat#isAtLeastN()}.
-            return Build.VERSION.SDK_INT > Build.VERSION_CODES.M || BuildCompat.isAtLeastN();
-        }
+                    if (Utils.isDeveloper()) {
+                        // we enable tuner for developers to test tuner in any platform.
+                        return true;
+                    }
 
-    };
+                    // This is special handling just for USB Tuner.
+                    // It does not require any N API's but relies on a improvements in N for AC3 support
+                    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
+                }
+            };
+
+    /**
+     * Use network tuner if it is available and there is no other tuner types.
+     */
+    public static final Feature NETWORK_TUNER =
+            new Feature() {
+                @Override
+                public boolean isEnabled(Context context) {
+                    if (!TUNER.isEnabled(context)) {
+                        return false;
+                    }
+                    if (Utils.isDeveloper()) {
+                        // Network tuner will be enabled for developers.
+                        return true;
+                    }
+                    return Locale.US.getCountry().equalsIgnoreCase(
+                            LocationUtils.getCurrentCountry(context));
+                }
+            };
 
     private static final String GSERVICE_KEY_UNHIDE = "live_channels_unhide";
     /**
@@ -82,22 +115,75 @@
                 }
             });
 
-    public static final Feature PICTURE_IN_PICTURE = new Feature() {
-        private Boolean mEnabled;
+    public static final Feature PICTURE_IN_PICTURE =
+            new Feature() {
+                private Boolean mEnabled;
 
-        @Override
-        public boolean isEnabled(Context context) {
-            if (mEnabled == null) {
-                mEnabled = context.getPackageManager().hasSystemFeature(
-                        PackageManager.FEATURE_PICTURE_IN_PICTURE);
-            }
-            return mEnabled;
-        }
-    };
+                @Override
+                public boolean isEnabled(Context context) {
+                    if (mEnabled == null) {
+                        mEnabled =
+                                Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+                                        && context.getPackageManager()
+                                                .hasSystemFeature(
+                                                        PackageManager.FEATURE_PICTURE_IN_PICTURE);
+                    }
+                    return mEnabled;
+                }
+            };
 
-    /**
-     * Enable a conflict dialog between currently watched channel and upcoming recording.
-     */
+    /** Use AC3 software decode. */
+    public static final Feature AC3_SOFTWARE_DECODE =
+            new Feature() {
+                private final String[] SUPPORTED_REGIONS = {};
+
+                private Boolean mEnabled;
+
+                @Override
+                public boolean isEnabled(Context context) {
+                    if (mEnabled == null) {
+                        if (mEnabled == null) {
+                            // We will not cache the result of fallback solution.
+                            String country = LocationUtils.getCurrentCountry(context);
+                            for (int i = 0; i < SUPPORTED_REGIONS.length; ++i) {
+                                if (SUPPORTED_REGIONS[i].equalsIgnoreCase(country)) {
+                                    return true;
+                                }
+                            }
+                            if (DEBUG) Log.d(TAG, "AC3 flag false after country check");
+                            return false;
+                        }
+                    }
+                    if (DEBUG) Log.d(TAG, "AC3 flag " + mEnabled);
+                    return mEnabled;
+                }
+            };
+
+    /** Show postal code fragment before channel scan. */
+    public static final Feature ENABLE_CLOUD_EPG_REGION =
+            new Feature() {
+                private final String[] SUPPORTED_REGIONS = {
+                };
+
+
+                @Override
+                public boolean isEnabled(Context context) {
+                    if (!Experiments.CLOUD_EPG.get()) {
+                        if (DEBUG) Log.d(TAG, "Experiments.CLOUD_EPG is false");
+                        return false;
+                    }
+                    String country = LocationUtils.getCurrentCountry(context);
+                    for (int i = 0; i < SUPPORTED_REGIONS.length; i++) {
+                        if (SUPPORTED_REGIONS[i].equalsIgnoreCase(country)) {
+                            return true;
+                        }
+                    }
+                    if (DEBUG) Log.d(TAG, "EPG flag false after country check");
+                    return false;
+                }
+            };
+
+    /** Enable a conflict dialog between currently watched channel and upcoming recording. */
     public static final Feature SHOW_UPCOMING_CONFLICT_DIALOG = OFF;
 
     /**
@@ -105,6 +191,11 @@
      */
     public static final Feature USE_PARTNER_INPUT_BLACKLIST = ON;
 
+    /**
+     * Enable Dvb parsers and listeners.
+     */
+    public static final Feature ENABLE_FILE_DVB = OFF;
+
     @VisibleForTesting
     public static final Feature TEST_FEATURE = new PropertyFeature("test_feature", false);
 
diff --git a/src/com/android/tv/InputSessionManager.java b/src/com/android/tv/InputSessionManager.java
index e4b0f45..2978f40 100644
--- a/src/com/android/tv/InputSessionManager.java
+++ b/src/com/android/tv/InputSessionManager.java
@@ -37,7 +37,6 @@
 import android.util.ArraySet;
 import android.util.Log;
 
-import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.ui.TunableTvView;
 import com.android.tv.ui.TunableTvView.OnTuneListener;
@@ -73,6 +72,8 @@
             Collections.synchronizedSet(new ArraySet<>());
     private final Set<OnTvViewChannelChangeListener> mOnTvViewChannelChangeListeners =
             new ArraySet<>();
+    private final Set<OnRecordingSessionChangeListener> mOnRecordingSessionChangeListeners =
+            new ArraySet<>();
 
     public InputSessionManager(Context context) {
         mContext = context.getApplicationContext();
@@ -113,6 +114,9 @@
         RecordingSession session = new RecordingSession(inputId, tag, callback, handler, endTimeMs);
         mRecordingSessions.add(session);
         if (DEBUG) Log.d(TAG, "Recording session created: " + session);
+        for (OnRecordingSessionChangeListener listener : mOnRecordingSessionChangeListeners) {
+            listener.onRecordingSessionChange(true, mRecordingSessions.size());
+        }
         return session;
     }
 
@@ -123,6 +127,9 @@
         mRecordingSessions.remove(session);
         session.release();
         if (DEBUG) Log.d(TAG, "Recording session released: " + session);
+        for (OnRecordingSessionChangeListener listener : mOnRecordingSessionChangeListeners) {
+            listener.onRecordingSessionChange(false, mRecordingSessions.size());
+        }
     }
 
     /**
@@ -148,9 +155,17 @@
         }
     }
 
-    /**
-     * Returns the current {@link TvView} channel.
-     */
+    /** Adds the {@link OnRecordingSessionChangeListener}. */
+    public void addOnRecordingSessionChangeListener(OnRecordingSessionChangeListener listener) {
+        mOnRecordingSessionChangeListeners.add(listener);
+    }
+
+    /** Removes the {@link OnRecordingSessionChangeListener}. */
+    public void removeRecordingSessionChangeListener(OnRecordingSessionChangeListener listener) {
+        mOnRecordingSessionChangeListeners.remove(listener);
+    }
+
+    /** Returns the current {@link TvView} channel. */
     @MainThread
     public Uri getCurrentTvViewChannelUri() {
         for (TvViewSession session : mTvViewSessions) {
@@ -249,7 +264,7 @@
             mTvView.setCallback(new DelegateTvInputCallback(mCallback) {
                 @Override
                 public void onConnectionFailed(String inputId) {
-                    if (DEBUG) Log.d(TAG, "TvViewSession: commection failed");
+                    if (DEBUG) Log.d(TAG, "TvViewSession: connection failed");
                     mTuned = false;
                     mNeedToBeRetuned = false;
                     super.onConnectionFailed(inputId);
@@ -546,4 +561,9 @@
     public interface OnTvViewChannelChangeListener {
         void onTvViewChannelChange(@Nullable Uri channelUri);
     }
+
+    /** Called when recording session is created or destroyed. */
+    public interface OnRecordingSessionChangeListener {
+        void onRecordingSessionChange(boolean create, int count);
+    }
 }
diff --git a/src/com/android/tv/MainActivity.java b/src/com/android/tv/MainActivity.java
index 58850b5..ed5f79a 100644
--- a/src/com/android/tv/MainActivity.java
+++ b/src/com/android/tv/MainActivity.java
@@ -27,14 +27,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Point;
 import android.hardware.display.DisplayManager;
-import android.media.AudioManager;
-import android.media.MediaMetadata;
-import android.media.session.MediaSession;
-import android.media.session.PlaybackState;
 import android.media.tv.TvContentRating;
 import android.media.tv.TvContract;
 import android.media.tv.TvContract.Channels;
@@ -44,7 +37,6 @@
 import android.media.tv.TvTrackInfo;
 import android.media.tv.TvView.OnUnhandledInputEventListener;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -71,7 +63,6 @@
 import android.widget.FrameLayout;
 import android.widget.Toast;
 
-import com.android.tv.analytics.DurationTimer;
 import com.android.tv.analytics.SendChannelStatusRunnable;
 import com.android.tv.analytics.SendConfigInfoRunnable;
 import com.android.tv.analytics.Tracker;
@@ -91,26 +82,30 @@
 import com.android.tv.data.StreamInfo;
 import com.android.tv.data.WatchedHistoryManager;
 import com.android.tv.data.epg.EpgFetcher;
+import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dialog.PinDialogFragment;
+import com.android.tv.dialog.PinDialogFragment.OnPinCheckedListener;
 import com.android.tv.dialog.SafeDismissDialogFragment;
-import com.android.tv.dvr.ConflictChecker;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.recorder.ConflictChecker;
 import com.android.tv.dvr.ui.DvrStopRecordingFragment;
-import com.android.tv.dvr.ui.HalfSizedDialogFragment;
-import com.android.tv.experiments.Experiments;
+import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.menu.Menu;
 import com.android.tv.onboarding.OnboardingActivity;
 import com.android.tv.parental.ContentRatingsManager;
 import com.android.tv.parental.ParentalControlSettings;
-import com.android.tv.receiver.AudioCapabilitiesReceiver;
+import com.android.tv.perf.EventNames;
+import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.perf.StubPerformanceMonitor;
+import com.android.tv.perf.TimerEvent;
+import com.android.tv.recommendation.ChannelPreviewUpdater;
 import com.android.tv.recommendation.NotificationService;
 import com.android.tv.search.ProgramGuideSearchFragment;
+import com.android.tv.tuner.TunerInputController;
 import com.android.tv.tuner.TunerPreferences;
 import com.android.tv.tuner.setup.TunerSetupActivity;
 import com.android.tv.tuner.tvinput.TunerTvInputService;
-import com.android.tv.ui.AppLayerTvView;
 import com.android.tv.ui.ChannelBannerView;
 import com.android.tv.ui.InputBannerView;
 import com.android.tv.ui.KeypadChannelSwitchView;
@@ -128,23 +123,22 @@
 import com.android.tv.ui.sidepanel.MultiAudioFragment;
 import com.android.tv.ui.sidepanel.SettingsFragment;
 import com.android.tv.ui.sidepanel.SideFragment;
+import com.android.tv.ui.sidepanel.parentalcontrols.ParentalControlsFragment;
 import com.android.tv.util.AccountHelper;
 import com.android.tv.util.CaptionSettings;
+import com.android.tv.util.Debug;
+import com.android.tv.util.DurationTimer;
 import com.android.tv.util.ImageCache;
-import com.android.tv.util.ImageLoader;
 import com.android.tv.util.OnboardingUtils;
 import com.android.tv.util.PermissionUtils;
-import com.android.tv.util.PipInputManager;
-import com.android.tv.util.PipInputManager.PipInput;
 import com.android.tv.util.RecurringRunner;
-import com.android.tv.util.SearchManagerHelper;
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.SystemProperties;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.TvSettings;
-import com.android.tv.util.TvSettings.PipSound;
 import com.android.tv.util.TvTrackInfoUtils;
 import com.android.tv.util.Utils;
+import com.android.tv.util.ViewCache;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -159,8 +153,7 @@
 /**
  * The main activity for the Live TV app.
  */
-public class MainActivity extends Activity implements AudioManager.OnAudioFocusChangeListener,
-        OnActionClickListener {
+public class MainActivity extends Activity implements OnActionClickListener, OnPinCheckedListener {
     private static final String TAG = "MainActivity";
     private static final boolean DEBUG = false;
 
@@ -175,18 +168,11 @@
 
     private static final boolean USE_BACK_KEY_LONG_PRESS = false;
 
-    private static final float AUDIO_MAX_VOLUME = 1.0f;
-    private static final float AUDIO_MIN_VOLUME = 0.0f;
-    private static final float AUDIO_DUCKING_VOLUME = 0.3f;
     private static final float FRAME_RATE_FOR_FILM = 23.976f;
     private static final float FRAME_RATE_EPSILON = 0.1f;
 
-    private static final float MEDIA_SESSION_STOPPED_SPEED = 0.0f;
-    private static final float MEDIA_SESSION_PLAYING_SPEED = 1.0f;
-
 
     private static final int PERMISSIONS_REQUEST_READ_TV_LISTINGS = 1;
-    private static final int PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 2;
     private static final String PERMISSION_READ_TV_LISTINGS = "android.permission.READ_TV_LISTINGS";
 
     // Tracker screen names.
@@ -211,49 +197,26 @@
     }
 
 
+    private static final IntentFilter SYSTEM_INTENT_FILTER = new IntentFilter();
+    static {
+        SYSTEM_INTENT_FILTER.addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
+        SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_SCREEN_OFF);
+        SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_SCREEN_ON);
+        SYSTEM_INTENT_FILTER.addAction(Intent.ACTION_TIME_CHANGED);
+    }
+
     private static final int REQUEST_CODE_START_SETUP_ACTIVITY = 1;
-    private static final int REQUEST_CODE_START_SYSTEM_CAPTIONING_SETTINGS = 2;
 
     private static final String KEY_INIT_CHANNEL_ID = "com.android.tv.init_channel_id";
 
-    private static final String MEDIA_SESSION_TAG = "com.android.tv.mediasession";
-
     // Change channels with key long press.
     private static final int CHANNEL_CHANGE_NORMAL_SPEED_DURATION_MS = 3000;
     private static final int CHANNEL_CHANGE_DELAY_MS_IN_MAX_SPEED = 50;
     private static final int CHANNEL_CHANGE_DELAY_MS_IN_NORMAL_SPEED = 200;
     private static final int CHANNEL_CHANGE_INITIAL_DELAY_MILLIS = 500;
-    private static final int FIRST_STREAM_INFO_UPDATE_DELAY_MILLIS = 500;
 
     private static final int MSG_CHANNEL_DOWN_PRESSED = 1000;
     private static final int MSG_CHANNEL_UP_PRESSED = 1001;
-    private static final int MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE = 1002;
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW, UPDATE_CHANNEL_BANNER_REASON_TUNE,
-        UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST, UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO,
-        UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK})
-    private @interface ChannelBannerUpdateReason {}
-    /**
-     * Updates channel banner because the channel banner is forced to show.
-     */
-    private static final int UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW = 1;
-    /**
-     * Updates channel banner because of tuning.
-     */
-    private static final int UPDATE_CHANNEL_BANNER_REASON_TUNE = 2;
-    /**
-     * Updates channel banner because of fast tuning.
-     */
-    private static final int UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST = 3;
-    /**
-     * Updates channel banner because of info updating.
-     */
-    private static final int UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO = 4;
-    /**
-     * Updates channel banner because the current watched channel is locked or unlocked.
-     */
-    private static final int UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK = 5;
 
     private static final int TVVIEW_SET_MAIN_TIMEOUT_MS = 3000;
 
@@ -261,12 +224,14 @@
     // Delay 1 second in order not to interrupt the first tune.
     private static final long LAZY_INITIALIZATION_DELAY = TimeUnit.SECONDS.toMillis(1);
 
+    private static final int UNDEFINED_TRACK_INDEX = -1;
+    private static final long START_UP_TIMER_RESET_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(3);
+
     private AccessibilityManager mAccessibilityManager;
     private ChannelDataManager mChannelDataManager;
     private ProgramDataManager mProgramDataManager;
     private TvInputManagerHelper mTvInputManagerHelper;
     private ChannelTuner mChannelTuner;
-    private PipInputManager mPipInputManager;
     private final TvOptionsManager mTvOptionsManager = new TvOptionsManager(this);
     private TvViewUiManager mTvViewUiManager;
     private TimeShiftManager mTimeShiftManager;
@@ -278,12 +243,7 @@
 
     private View mContentView;
     private TunableTvView mTvView;
-    private TunableTvView mPipView;
     private Bundle mTuneParams;
-    private boolean mChannelBannerHiddenBySideFragment;
-    // TODO: Move the scene views into TvTransitionManager or TvOverlayManager.
-    private ChannelBannerView mChannelBannerView;
-    private KeypadChannelSwitchView mKeypadChannelSwitchView;
     @Nullable
     private Uri mInitChannelUri;
     @Nullable
@@ -293,20 +253,13 @@
     private boolean mShowSelectInputView;
     private TvInputInfo mInputToSetUp;
     private final List<MemoryManageable> mMemoryManageables = new ArrayList<>();
-    private MediaSession mMediaSession;
-    private int mNowPlayingCardWidth;
-    private int mNowPlayingCardHeight;
+    private MediaSessionWrapper mMediaSessionWrapper;
     private final MyOnTuneListener mOnTuneListener = new MyOnTuneListener();
 
     private String mInputIdUnderSetup;
     private boolean mIsSetupActivityCalledByPopup;
-    private AudioManager mAudioManager;
-    private int mAudioFocusStatus;
+    private AudioManagerHelper mAudioManagerHelper;
     private boolean mTunePending;
-    private boolean mPipEnabled;
-    private Channel mPipChannel;
-    private boolean mPipSwap;
-    @PipSound private int mPipSound = TvSettings.PIP_SOUND_MAIN; // Default
     private boolean mDebugNonFullSizeScreen;
     private boolean mActivityResumed;
     private boolean mActivityStarted;
@@ -316,10 +269,10 @@
     private boolean mBackKeyPressed;
     private boolean mNeedShowBackKeyGuide;
     private boolean mVisibleBehind;
-    private boolean mAc3PassthroughSupported;
     private boolean mShowNewSourcesFragment = true;
     private String mTunerInputId;
     private boolean mOtherActivityLaunched;
+    private PerformanceMonitor mPerformanceMonitor;
 
     private boolean mIsFilmModeSet;
     private float mDefaultRefreshRate;
@@ -331,11 +284,8 @@
     private boolean mIsCurrentChannelUnblockedByUser;
     private boolean mWasChannelUnblockedBeforeShrunkenByUser;
     private Channel mChannelBeforeShrunkenTvView;
-    private Channel mPipChannelBeforeShrunkenTvView;
     private boolean mIsCompletingShrunkenTvView;
 
-    // TODO: Need to consider the case that TIS explicitly request PIN code while TV view is
-    // shrunken.
     private TvContentRating mLastAllowedRatingForCurrentChannel;
     private TvContentRating mAllowedRatingBeforeShrunken;
 
@@ -346,42 +296,46 @@
     private static final int MAX_RECENT_CHANNELS = 5;
     private final ArrayDeque<Long> mRecentChannels = new ArrayDeque<>(MAX_RECENT_CHANNELS);
 
-    private AudioCapabilitiesReceiver mAudioCapabilitiesReceiver;
     private RecurringRunner mSendConfigInfoRecurringRunner;
     private RecurringRunner mChannelStatusRecurringRunner;
 
-    // A caller which started this activity. (e.g. TvSearch)
-    private String mSource;
-
     private final Handler mHandler = new MainActivityHandler(this);
     private final Set<OnActionClickListener> mOnActionClickListeners = new ArraySet<>();
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
-                if (DEBUG) Log.d(TAG, "Received ACTION_SCREEN_OFF");
-                // We need to stop TvView, when the screen is turned off. If not and TIS uses
-                // MediaPlayer, a device may not go to the sleep mode and audio can be heard,
-                // because MediaPlayer keeps playing media by its wake lock.
-                mScreenOffIntentReceived = true;
-                markCurrentChannelDuringScreenOff();
-                stopAll(true);
-            } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
-                if (DEBUG) Log.d(TAG, "Received ACTION_SCREEN_ON");
-                if (!mActivityResumed && mVisibleBehind) {
-                    // ACTION_SCREEN_ON is usually called after onResume. But, if media is played
-                    // under launcher with requestVisibleBehind(true), onResume will not be called.
-                    // In this case, we need to resume TvView and PipView explicitly.
-                    resumeTvIfNeeded();
-                    resumePipIfNeeded();
-                }
-            } else if (intent.getAction().equals(
-                    TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED)) {
-                if (DEBUG) Log.d(TAG, "Received parental control settings change");
-                checkChannelLockNeeded(mTvView);
-                checkChannelLockNeeded(mPipView);
-                applyParentalControlSettings();
+            switch (intent.getAction()) {
+                case Intent.ACTION_SCREEN_OFF:
+                    if (DEBUG) Log.d(TAG, "Received ACTION_SCREEN_OFF");
+                    // We need to stop TvView, when the screen is turned off. If not and TIS uses
+                    // MediaPlayer, a device may not go to the sleep mode and audio can be heard,
+                    // because MediaPlayer keeps playing media by its wake lock.
+                    mScreenOffIntentReceived = true;
+                    markCurrentChannelDuringScreenOff();
+                    stopAll(true);
+                    break;
+                case Intent.ACTION_SCREEN_ON:
+                    if (DEBUG) Log.d(TAG, "Received ACTION_SCREEN_ON");
+                    if (!mActivityResumed && mVisibleBehind) {
+                        // ACTION_SCREEN_ON is usually called after onResume. But, if media is
+                        // played under launcher with requestVisibleBehind(true), onResume will
+                        // not be called. In this case, we need to resume TvView explicitly.
+                        resumeTvIfNeeded();
+                    }
+                    break;
+                case TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED:
+                    if (DEBUG) Log.d(TAG, "Received parental control settings change");
+                    applyParentalControlSettings();
+                    checkChannelLockNeeded(mTvView, null);
+                    break;
+                case Intent.ACTION_TIME_CHANGED:
+                    // Re-tune the current channel to prevent incorrect behavior of trick-play.
+                    // See: b/37393628
+                    if (mChannelTuner.getCurrentChannel() != null) {
+                        tune(true);
+                    }
+                    break;
             }
         }
     };
@@ -397,8 +351,9 @@
             }
             Channel channel = mTvView.getCurrentChannel();
             if (channel != null && channel.getId() == channelId) {
-                updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
-                updateMediaSession();
+                mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                        TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
+                mMediaSessionWrapper.update(mTvView.isBlocked(), channel, program);
             }
         }
     };
@@ -407,36 +362,39 @@
             new ChannelTuner.Listener() {
                 @Override
                 public void onLoadFinished() {
+                    Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+                            "MainActivity.mChannelTunerListener.onLoadFinished");
                     SetupUtils.getInstance(MainActivity.this).markNewChannelsBrowsable();
                     if (mActivityResumed) {
                         resumeTvIfNeeded();
-                        resumePipIfNeeded();
                     }
-                    mKeypadChannelSwitchView.setChannels(mChannelTuner.getBrowsableChannelList());
+                    mOverlayManager.onBrowsableChannelsUpdated();
                 }
 
                 @Override
                 public void onBrowsableChannelListChanged() {
-                    mKeypadChannelSwitchView.setChannels(mChannelTuner.getBrowsableChannelList());
+                    mOverlayManager.onBrowsableChannelsUpdated();
                 }
 
                 @Override
                 public void onCurrentChannelUnavailable(Channel channel) {
-                    // TODO: handle the case that a channel is suddenly removed from DB.
+                    if (mChannelTuner.moveToAdjacentBrowsableChannel(true)) {
+                        tune(true);
+                    } else {
+                        stopTv("onCurrentChannelUnavailable()", false);
+                    }
                 }
 
                 @Override
-                public void onChannelChanged(Channel previousChannel, Channel currentChannel) {
-                }
+                public void onChannelChanged(Channel previousChannel, Channel currentChannel) {}
             };
 
-    private final Runnable mRestoreMainViewRunnable =
-            new Runnable() {
-                @Override
-                public void run() {
-                    restoreMainTvView();
-                }
-            };
+    private final Runnable mRestoreMainViewRunnable = new Runnable() {
+        @Override
+        public void run() {
+            restoreMainTvView();
+        }
+    };
     private ProgramGuideSearchFragment mSearchFragment;
 
     private final TvInputCallback mTvInputCallback = new TvInputCallback() {
@@ -456,54 +414,54 @@
         boolean parentalControlEnabled = mTvInputManagerHelper.getParentalControlSettings()
                 .isParentalControlsEnabled();
         mTvView.onParentalControlChanged(parentalControlEnabled);
-        mPipView.onParentalControlChanged(parentalControlEnabled);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            ChannelPreviewUpdater.getInstance(this).updatePreviewDataForChannelsImmediately();
+        }
     }
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+        TimerEvent timer = StubPerformanceMonitor.startBootstrapTimer();
+        DurationTimer startUpDebugTimer = Debug.getTimer(Debug.TAG_START_UP_TIMER);
+        if (!startUpDebugTimer.isStarted()
+                || startUpDebugTimer.getDuration() > START_UP_TIMER_RESET_THRESHOLD_MS) {
+            // TvApplication can start by other reason before MainActivty is launched.
+            // In this case, we restart the timer.
+            startUpDebugTimer.start();
+        }
+        startUpDebugTimer.log("MainActivity.onCreate");
         if (DEBUG) Log.d(TAG,"onCreate()");
         TvApplication.setCurrentRunningProcess(this, true);
         super.onCreate(savedInstanceState);
-
-        boolean isPassthroughInput = TvContract.isChannelUriForPassthroughInput(getIntent()
-                .getData());
-        boolean skipToShowOnboarding = Intent.ACTION_VIEW.equals(getIntent().getAction())
-                && isPassthroughInput;
-        if (OnboardingUtils.needToShowOnboarding(this) && !skipToShowOnboarding
-                && !TvCommonUtils.isRunningInTest()) {
-            // TODO: The onboarding is turned off in test, because tests are broken by the
-            // onboarding. We need to enable the feature for tests later.
-            startActivity(OnboardingActivity.buildIntent(this, getIntent()));
-            finish();
+        ApplicationSingletons applicationSingletons = TvApplication.getSingletons(this);
+        if (!applicationSingletons.getTvInputManagerHelper().hasTvInputManager()) {
+            Log.wtf(TAG, "Stopping because device does not have a TvInputManager");
+            finishAndRemoveTask();
             return;
         }
+        mPerformanceMonitor = applicationSingletons.getPerformanceMonitor();
 
-        // Check this permission for the EPG fetch.
-        // TODO: check {@link shouldShowRequestPermissionRationale}.
-        // While testing, no way to allow the permission when the dialog shows up. So we'd better
-        // not show the dialog.
-        if (!TvCommonUtils.isRunningInTest() && Utils.hasInternalTvInputs(this, true)
-                && checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED) {
-            requestPermissions(new String[] {android.Manifest.permission.ACCESS_COARSE_LOCATION},
-                    PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
+        TvApplication tvApplication = (TvApplication) getApplication();
+        mChannelDataManager = tvApplication.getChannelDataManager();
+        // In API 23, TvContract.isChannelUriForPassthroughInput is hidden.
+        boolean isPassthroughInput =
+                TvContract.isChannelUriForPassthroughInput(getIntent().getData());
+        boolean tuneToPassthroughInput = Intent.ACTION_VIEW.equals(getIntent().getAction())
+                && isPassthroughInput;
+        boolean channelLoadedAndNoChannelAvailable = mChannelDataManager.isDbLoadFinished()
+                && mChannelDataManager.getChannelCount() <= 0;
+        if ((OnboardingUtils.isFirstRunWithCurrentVersion(this)
+                || channelLoadedAndNoChannelAvailable)
+                && !tuneToPassthroughInput
+                && !TvCommonUtils.isRunningInTest()) {
+            startOnboardingActivity();
+            return;
         }
-
-        DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
-        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
-        Point size = new Point();
-        display.getSize(size);
-        int screenWidth = size.x;
-        int screenHeight = size.y;
-        mDefaultRefreshRate = display.getRefreshRate();
-
         setContentView(R.layout.activity_tv);
-        mContentView = findViewById(android.R.id.content);
+        mProgramDataManager = tvApplication.getProgramDataManager();
+        mTvInputManagerHelper = tvApplication.getTvInputManagerHelper();
         mTvView = (TunableTvView) findViewById(R.id.main_tunable_tv_view);
-        int shrunkenTvViewHeight = getResources().getDimensionPixelSize(
-                R.dimen.shrunken_tvview_height);
-        mTvView.initialize((AppLayerTvView) findViewById(R.id.main_tv_view), false, screenHeight,
-                shrunkenTvViewHeight);
+        mTvView.initialize(mProgramDataManager, mTvInputManagerHelper);
         mTvView.setOnUnhandledInputEventListener(new OnUnhandledInputEventListener() {
             @Override
             public boolean onUnhandledInputEvent(InputEvent event) {
@@ -526,7 +484,6 @@
                 return false;
             }
         });
-
         long channelId = Utils.getLastWatchedChannelId(this);
         String inputId = Utils.getLastWatchedTunerInputId(this);
         if (!isPassthroughInput && inputId != null
@@ -534,27 +491,21 @@
             mTvView.warmUpInput(inputId, TvContract.buildChannelUri(channelId));
         }
 
-        TvApplication tvApplication = (TvApplication) getApplication();
         tvApplication.getMainActivityWrapper().onMainActivityCreated(this);
         if (BuildConfig.ENG && SystemProperties.ALLOW_STRICT_MODE.getValue()) {
             Toast.makeText(this, "Using Strict Mode for eng builds", Toast.LENGTH_SHORT).show();
         }
         mTracker = tvApplication.getTracker();
-        mTvInputManagerHelper = tvApplication.getTvInputManagerHelper();
         if (Features.TUNER.isEnabled(this)) {
             mTvInputManagerHelper.addCallback(mTvInputCallback);
         }
         mTunerInputId = TunerTvInputService.getInputId(this);
-        mChannelDataManager = tvApplication.getChannelDataManager();
-        mProgramDataManager = tvApplication.getProgramDataManager();
         mProgramDataManager.addOnCurrentProgramUpdatedListener(Channel.INVALID_ID,
                 mOnCurrentProgramUpdatedListener);
         mProgramDataManager.setPrefetchEnabled(true);
         mChannelTuner = new ChannelTuner(mChannelDataManager, mTvInputManagerHelper);
         mChannelTuner.addListener(mChannelTunerListener);
         mChannelTuner.start();
-        mPipInputManager = new PipInputManager(this, mTvInputManagerHelper, mChannelTuner);
-        mPipInputManager.start();
         mMemoryManageables.add(mProgramDataManager);
         mMemoryManageables.add(ImageCache.getInstance());
         mMemoryManageables.add(TvContentRatingCache.getInstance());
@@ -565,28 +516,29 @@
                 new OnCurrentProgramUpdatedListener() {
                     @Override
                     public void onCurrentProgramUpdated(long channelId, Program program) {
-                        updateMediaSession();
+                        mMediaSessionWrapper.update(mTvView.isBlocked(), getCurrentChannel(),
+                                program);
                         switch (mTimeShiftManager.getLastActionId()) {
                             case TimeShiftManager.TIME_SHIFT_ACTION_ID_REWIND:
                             case TimeShiftManager.TIME_SHIFT_ACTION_ID_FAST_FORWARD:
                             case TimeShiftManager.TIME_SHIFT_ACTION_ID_JUMP_TO_PREVIOUS:
                             case TimeShiftManager.TIME_SHIFT_ACTION_ID_JUMP_TO_NEXT:
-                                updateChannelBannerAndShowIfNeeded(
-                                        UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
+                                mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                                        TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
                                 break;
                             case TimeShiftManager.TIME_SHIFT_ACTION_ID_PAUSE:
                             case TimeShiftManager.TIME_SHIFT_ACTION_ID_PLAY:
                             default:
-                                updateChannelBannerAndShowIfNeeded(
-                                        UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
+                                mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                                        TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
                                 break;
                         }
                     }
                 });
 
-        mPipView = (TunableTvView) findViewById(R.id.pip_tunable_tv_view);
-        mPipView.initialize((AppLayerTvView) findViewById(R.id.pip_tv_view), true, screenHeight,
-                shrunkenTvViewHeight);
+        DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
+        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        mDefaultRefreshRate = display.getRefreshRate();
 
         if (!PermissionUtils.hasAccessWatchedHistory(this)) {
             WatchedHistoryManager watchedHistoryManager = new WatchedHistoryManager(
@@ -594,17 +546,15 @@
             watchedHistoryManager.start();
             mTvView.setWatchedHistoryManager(watchedHistoryManager);
         }
-        mTvViewUiManager = new TvViewUiManager(this, mTvView, mPipView,
+        mTvViewUiManager = new TvViewUiManager(this, mTvView,
                 (FrameLayout) findViewById(android.R.id.content), mTvOptionsManager);
 
-        mPipView.setFixedSurfaceSize(screenWidth / 2, screenHeight / 2);
-        mPipView.setBlockScreenType(TunableTvView.BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW);
-
+        mContentView = findViewById(android.R.id.content);
         ViewGroup sceneContainer = (ViewGroup) findViewById(R.id.scene_container);
-        mChannelBannerView = (ChannelBannerView) getLayoutInflater().inflate(
+        ChannelBannerView channelBannerView = (ChannelBannerView) getLayoutInflater().inflate(
                 R.layout.channel_banner, sceneContainer, false);
-        mKeypadChannelSwitchView = (KeypadChannelSwitchView) getLayoutInflater().inflate(
-                R.layout.keypad_channel_switch, sceneContainer, false);
+        KeypadChannelSwitchView keypadChannelSwitchView = (KeypadChannelSwitchView)
+                getLayoutInflater().inflate(R.layout.keypad_channel_switch, sceneContainer, false);
         InputBannerView inputBannerView = (InputBannerView) getLayoutInflater()
                 .inflate(R.layout.input_banner, sceneContainer, false);
         SelectInputView selectInputView = (SelectInputView) getLayoutInflater()
@@ -641,26 +591,12 @@
             }
         });
         mSearchFragment = new ProgramGuideSearchFragment();
-        mOverlayManager = new TvOverlayManager(this, mChannelTuner, mTvView,
-                mKeypadChannelSwitchView, mChannelBannerView, inputBannerView,
+        mOverlayManager = new TvOverlayManager(this, mChannelTuner, mTvView, mTvOptionsManager,
+                keypadChannelSwitchView, channelBannerView, inputBannerView,
                 selectInputView, sceneContainer, mSearchFragment);
 
-        mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
-        mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
-
-        mMediaSession = new MediaSession(this, MEDIA_SESSION_TAG);
-        mMediaSession.setCallback(new MediaSession.Callback() {
-            @Override
-            public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) {
-                // Consume the media button event here. Should not send it to other apps.
-                return true;
-            }
-        });
-        mMediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
-                MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
-        mNowPlayingCardWidth = getResources().getDimensionPixelSize(
-                R.dimen.notif_card_img_max_width);
-        mNowPlayingCardHeight = getResources().getDimensionPixelSize(R.dimen.notif_card_img_height);
+        mAudioManagerHelper = new AudioManagerHelper(this, mTvView);
+        mMediaSessionWrapper = new MediaSessionWrapper(this);
 
         mTvViewUiManager.restoreDisplayMode(false);
         if (!handleIntent(getIntent())) {
@@ -668,15 +604,6 @@
             return;
         }
 
-        mAudioCapabilitiesReceiver = new AudioCapabilitiesReceiver(this,
-                new AudioCapabilitiesReceiver.OnAc3PassthroughCapabilityChangeListener() {
-                    @Override
-                    public void onAc3PassthroughCapabilityChange(boolean capability) {
-                        mAc3PassthroughSupported = capability;
-                    }
-                });
-        mAudioCapabilitiesReceiver.register();
-
         mAccessibilityManager =
                 (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
         mSendConfigInfoRecurringRunner = new RecurringRunner(this, TimeUnit.DAYS.toMillis(1),
@@ -692,6 +619,13 @@
             mDvrConflictChecker = new ConflictChecker(this);
         }
         initForTest();
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.onCreate end");
+        mPerformanceMonitor.stopTimer(timer, EventNames.MAIN_ACTIVITY_ONCREATE);
+    }
+
+    private void startOnboardingActivity() {
+        startActivity(OnboardingActivity.buildIntent(this, getIntent()));
+        finish();
     }
 
     @Override
@@ -705,32 +639,21 @@
     @Override
     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
             @NonNull int[] grantResults) {
-        switch (requestCode) {
-            case PERMISSIONS_REQUEST_READ_TV_LISTINGS:
-                if (grantResults.length > 0
-                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-                    // Start reload of dependent data
-                    mChannelDataManager.reload();
-                    mProgramDataManager.reload();
+        if (requestCode == PERMISSIONS_REQUEST_READ_TV_LISTINGS) {
+            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                // Start reload of dependent data
+                mChannelDataManager.reload();
+                mProgramDataManager.reload();
 
-                    // Restart live channels.
-                    Intent intent = getIntent();
-                    finish();
-                    startActivity(intent);
-                } else {
-                    Toast.makeText(this, R.string.msg_read_tv_listing_permission_denied,
-                            Toast.LENGTH_LONG).show();
-                    finish();
-                }
-                break;
-            case PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION:
-                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
-                        && Experiments.CLOUD_EPG.get()) {
-                    EpgFetcher.getInstance(this).startImmediately();
-                } else {
-                    EpgFetcher.getInstance(this).stop();
-                }
-                break;
+                // Restart live channels.
+                Intent intent = getIntent();
+                finish();
+                startActivity(intent);
+            } else {
+                Toast.makeText(this, R.string.msg_read_tv_listing_permission_denied,
+                        Toast.LENGTH_LONG).show();
+                finish();
+            }
         }
     }
 
@@ -781,6 +704,7 @@
 
     @Override
     protected void onStart() {
+        TimerEvent timer = mPerformanceMonitor.startTimer();
         if (DEBUG) Log.d(TAG,"onStart()");
         super.onStart();
         mScreenOffIntentReceived = false;
@@ -789,23 +713,25 @@
         mMainDurationTimer.start();
 
         applyParentalControlSettings();
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(TvInputManager.ACTION_PARENTAL_CONTROLS_ENABLED_CHANGED);
-        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
-        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
-        registerReceiver(mBroadcastReceiver, intentFilter);
+        registerReceiver(mBroadcastReceiver, SYSTEM_INTENT_FILTER);
 
-        Intent notificationIntent = new Intent(this, NotificationService.class);
-        notificationIntent.setAction(NotificationService.ACTION_SHOW_RECOMMENDATION);
-        startService(notificationIntent);
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+            Intent notificationIntent = new Intent(this, NotificationService.class);
+            notificationIntent.setAction(NotificationService.ACTION_SHOW_RECOMMENDATION);
+            startService(notificationIntent);
+        }
+        TunerInputController.executeNetworkTunerDiscoveryAsyncTask(this);
+
+        EpgFetcher.getInstance(this).fetchImmediatelyIfNeeded();
+        mPerformanceMonitor.stopTimer(timer, EventNames.MAIN_ACTIVITY_ONSTART);
     }
 
     @Override
     protected void onResume() {
+        TimerEvent timer = mPerformanceMonitor.startTimer();
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.onResume start");
         if (DEBUG) Log.d(TAG, "onResume()");
         super.onResume();
-        // Refresh the remote config, it is throttled automatically.
-        TvApplication.getSingletons(this).getRemoteConfig().fetch(null);
         if (!PermissionUtils.hasAccessAllEpg(this)
                 && checkSelfPermission(PERMISSION_READ_TV_LISTINGS)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -819,23 +745,23 @@
         mActivityResumed = true;
         mShowNewSourcesFragment = true;
         mOtherActivityLaunched = false;
-        int result = mAudioManager.requestAudioFocus(MainActivity.this,
-                AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
-        mAudioFocusStatus = (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) ?
-                AudioManager.AUDIOFOCUS_GAIN : AudioManager.AUDIOFOCUS_LOSS;
-        setVolumeByAudioFocusStatus();
+        mAudioManagerHelper.requestAudioFocus();
 
         if (mTvView.isPlaying()) {
             // Every time onResume() is called the activity will be assumed to not have requested
             // visible behind.
             requestVisibleBehind(true);
         }
-        if (Utils.hasRecordingFailedReason(getApplicationContext(),
-                TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE)) {
+        Set<String> failedScheduledRecordingInfoSet =
+                Utils.getFailedScheduledRecordingInfoSet(getApplicationContext());
+        if (Utils.hasRecordingFailedReason(
+                getApplicationContext(), TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE)
+                && !failedScheduledRecordingInfoSet.isEmpty()) {
             runAfterAttachedToWindow(new Runnable() {
                 @Override
                 public void run() {
-                    DvrUiHelper.showDvrInsufficientSpaceErrorDialog(MainActivity.this);
+                    DvrUiHelper.showDvrInsufficientSpaceErrorDialog(MainActivity.this,
+                            failedScheduledRecordingInfoSet);
                 }
             });
         }
@@ -843,13 +769,11 @@
         if (mChannelTuner.areAllChannelsLoaded()) {
             SetupUtils.getInstance(this).markNewChannelsBrowsable();
             resumeTvIfNeeded();
-            resumePipIfNeeded();
         }
         mOverlayManager.showMenuWithTimeShiftPauseIfNeeded();
 
-        // Note: The following codes are related to pop up an overlay UI after resume.
-        // When the following code is changed, please check the variable
-        // willShowOverlayUiAfterResume in updateChannelBannerAndShowIfNeeded.
+        // NOTE: The following codes are related to pop up an overlay UI after resume. When
+        // the following code is changed, please modify willShowOverlayUiWhenResume() accordingly.
         if (mInputToSetUp != null) {
             startSetupActivity(mInputToSetUp, false);
             mInputToSetUp = null;
@@ -881,6 +805,8 @@
         if (mDvrConflictChecker != null) {
             mDvrConflictChecker.start();
         }
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.onResume end");
+        mPerformanceMonitor.stopTimer(timer, EventNames.MAIN_ACTIVITY_ONRESUME);
     }
 
     @Override
@@ -893,18 +819,12 @@
         mActivityResumed = false;
         mOverlayManager.hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_DEFAULT);
         mTvView.setBlockScreenType(TunableTvView.BLOCK_SCREEN_TYPE_NO_UI);
-        if (mPipEnabled) {
-            mTvViewUiManager.hidePipForPause();
-        }
         mBackKeyPressed = false;
         mShowLockedChannelsTemporarily = false;
         mShouldTuneToTunerChannel = false;
         if (!mVisibleBehind) {
-            mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
-            mAudioManager.abandonAudioFocus(this);
-            if (mMediaSession.isActive()) {
-                mMediaSession.setActive(false);
-            }
+            mAudioManagerHelper.abandonAudioFocus();
+            mMediaSessionWrapper.setPlaybackState(false);
             mTracker.sendScreenView("");
         } else {
             mTracker.sendScreenView(SCREEN_BEHIND_NAME);
@@ -933,6 +853,32 @@
         return state;
     }
 
+    @Override
+    public void onPinChecked(boolean checked, int type, String rating) {
+        if (checked) {
+            switch (type) {
+                case PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_CHANNEL:
+                    blockOrUnblockScreen(mTvView, false);
+                    mIsCurrentChannelUnblockedByUser = true;
+                    break;
+                case PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM:
+                    TvContentRating unblockedRating = TvContentRating.unflattenFromString(rating);
+                    mLastAllowedRatingForCurrentChannel = unblockedRating;
+                    mTvView.unblockContent(unblockedRating);
+                    break;
+                case PinDialogFragment.PIN_DIALOG_TYPE_ENTER_PIN:
+                    mOverlayManager.getSideFragmentManager()
+                            .show(new ParentalControlsFragment(), false);
+                    // Pass through.
+                case PinDialogFragment.PIN_DIALOG_TYPE_NEW_PIN:
+                    mOverlayManager.getSideFragmentManager().showSidePanel(true);
+                    break;
+            }
+        } else if (type == PinDialogFragment.PIN_DIALOG_TYPE_ENTER_PIN) {
+            mOverlayManager.getSideFragmentManager().hideAll(false);
+        }
+    }
+
     private void resumeTvIfNeeded() {
         if (DEBUG) Log.d(TAG, "resumeTvIfNeeded()");
         if (!mTvView.isPlaying() || mInitChannelUri != null
@@ -962,21 +908,6 @@
         mTvView.setBlockScreenType(getDesiredBlockScreenType());
     }
 
-    private void resumePipIfNeeded() {
-        if (mPipEnabled && !(mPipView.isPlaying() && mPipView.isShown())) {
-            if (mPipInputManager.areInSamePipInput(
-                    mChannelTuner.getCurrentChannel(), mPipChannel)) {
-                enablePipView(false, false);
-            } else {
-                if (!mPipView.isPlaying()) {
-                    startPip(false);
-                } else {
-                    mTvViewUiManager.showPipForResume();
-                }
-            }
-        }
-    }
-
     private void startTv(Uri channelUri) {
         if (DEBUG) Log.d(TAG, "startTv Uri=" + channelUri);
         if ((channelUri == null || !TvContract.isChannelUriForPassthroughInput(channelUri))
@@ -993,7 +924,7 @@
             // TV has already started.
             if (channelUri == null || channelUri.equals(mChannelTuner.getCurrentChannelUri())) {
                 // Simply adjust the volume without tune.
-                setVolumeByAudioFocusStatus();
+                mAudioManagerHelper.setVolumeByAudioFocusStatus();
                 return;
             }
             stopTv();
@@ -1027,9 +958,9 @@
             }
         }
 
-        mTvView.start(mTvInputManagerHelper);
-        setVolumeByAudioFocusStatus();
-        tune();
+        mTvView.start();
+        mAudioManagerHelper.setVolumeByAudioFocusStatus();
+        tune(true);
     }
 
     @Override
@@ -1072,7 +1003,6 @@
     private void stopAll(boolean keepVisibleBehind) {
         mOverlayManager.hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_WITHOUT_ANIMATION);
         stopTv("stopAll()", keepVisibleBehind);
-        stopPip();
     }
 
     public TvInputManagerHelper getTvInputManagerHelper() {
@@ -1127,10 +1057,8 @@
 
     public void startSystemCaptioningSettingsActivity() {
         Intent intent = new Intent(Settings.ACTION_CAPTIONING_SETTINGS);
-        mOverlayManager.hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_WITHOUT_ANIMATION
-                | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_SIDE_PANEL_HISTORY);
         try {
-            startActivityForResultSafe(intent, REQUEST_CODE_START_SYSTEM_CAPTIONING_SETTINGS);
+            startActivitySafe(intent);
         } catch (ActivityNotFoundException e) {
             Toast.makeText(this, getString(R.string.msg_unable_to_start_system_captioning_settings),
                     Toast.LENGTH_SHORT).show();
@@ -1145,10 +1073,6 @@
         return mProgramDataManager;
     }
 
-    public PipInputManager getPipInputManager() {
-        return mPipInputManager;
-    }
-
     public TvOptionsManager getTvOptionsManager() {
         return mTvOptionsManager;
     }
@@ -1185,13 +1109,6 @@
     }
 
     /**
-     * Returns true if the current connected TV supports AC3 passthough.
-     */
-    public boolean isAc3PassthroughSupported() {
-        return mAc3PassthroughSupported;
-    }
-
-    /**
      * Returns the current program which the user is watching right now.<p>
      *
      * It might be a live program. If the time shifting is available, it can be a past program, too.
@@ -1218,8 +1135,6 @@
     }
 
     private Channel getBrowsableChannel() {
-        // TODO: mChannelMap could be dirty for a while when the browsablity of channels
-        // are changed. In that case, we shouldn't use the value from mChannelMap.
         Channel curChannel = mChannelTuner.getCurrentChannel();
         if (curChannel != null && curChannel.isBrowsable()) {
             return curChannel;
@@ -1254,9 +1169,7 @@
             // Show ChannelSourcesFragment only if all the channels are loaded.
             return;
         }
-        Channel currentChannel = mChannelTuner.getCurrentChannel();
-        long channelId = currentChannel == null ? Channel.INVALID_ID : currentChannel.getId();
-        mOverlayManager.getSideFragmentManager().show(new SettingsFragment(channelId));
+        mOverlayManager.getSideFragmentManager().show(new SettingsFragment());
     }
 
     public void showMerchantCollection() {
@@ -1272,19 +1185,11 @@
         mChannelBeforeShrunkenTvView = mTvView.getCurrentChannel();
         mWasChannelUnblockedBeforeShrunkenByUser = mIsCurrentChannelUnblockedByUser;
         mAllowedRatingBeforeShrunken = mLastAllowedRatingForCurrentChannel;
-
-        if (willMainViewBeTunerInput && mChannelTuner.isCurrentChannelPassthrough()
-                && mPipEnabled) {
-            mPipChannelBeforeShrunkenTvView = mPipChannel;
-            enablePipView(false, false);
-        } else {
-            mPipChannelBeforeShrunkenTvView = null;
-        }
         mTvViewUiManager.startShrunkenTvView();
 
         if (showLockedChannelsTemporarily) {
             mShowLockedChannelsTemporarily = true;
-            checkChannelLockNeeded(mTvView);
+            checkChannelLockNeeded(mTvView, null);
         }
 
         mTvView.setBlockScreenType(getDesiredBlockScreenType());
@@ -1320,23 +1225,15 @@
                     mIsCompletingShrunkenTvView = false;
                     mIsCurrentChannelUnblockedByUser = mWasChannelUnblockedBeforeShrunkenByUser;
                     mTvView.setBlockScreenType(getDesiredBlockScreenType());
-                    if (mPipChannelBeforeShrunkenTvView != null) {
-                        enablePipView(true, false);
-                        mPipChannelBeforeShrunkenTvView = null;
-                    }
                 }
             };
             mTvViewUiManager.fadeOutTvView(tuneAction);
             // Will automatically fade-in when video becomes available.
         } else {
-            checkChannelLockNeeded(mTvView);
+            checkChannelLockNeeded(mTvView, null);
             mIsCompletingShrunkenTvView = false;
             mIsCurrentChannelUnblockedByUser = mWasChannelUnblockedBeforeShrunkenByUser;
             mTvView.setBlockScreenType(getDesiredBlockScreenType());
-            if (mPipChannelBeforeShrunkenTvView != null) {
-                enablePipView(true, false);
-                mPipChannelBeforeShrunkenTvView = null;
-            }
         }
     }
 
@@ -1344,37 +1241,41 @@
         return mTvViewUiManager.isUnderShrunkenTvView() || mIsCompletingShrunkenTvView;
     }
 
+    /**
+     * Returns {@code true} if the tunable tv view is blocked by resource conflict or by parental
+     * control, otherwise {@code false}.
+     */
+    public boolean isScreenBlockedByResourceConflictOrParentalControl() {
+        return mTvView.getVideoUnavailableReason()
+                == TunableTvView.VIDEO_UNAVAILABLE_REASON_NO_RESOURCE || mTvView.isBlocked();
+    }
+
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        switch (requestCode) {
-            case REQUEST_CODE_START_SETUP_ACTIVITY:
-                if (resultCode == RESULT_OK) {
-                    int count = mChannelDataManager.getChannelCountForInput(mInputIdUnderSetup);
-                    String text;
-                    if (count > 0) {
-                        text = getResources().getQuantityString(R.plurals.msg_channel_added,
-                                count, count);
-                    } else {
-                        text = getString(R.string.msg_no_channel_added);
-                    }
-                    Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
-                    mInputIdUnderSetup = null;
-                    if (mChannelTuner.getCurrentChannel() == null) {
-                        mChannelTuner.moveToAdjacentBrowsableChannel(true);
-                    }
-                    if (mTunePending) {
-                        tune();
-                    }
+        if (requestCode == REQUEST_CODE_START_SETUP_ACTIVITY) {
+            if (resultCode == RESULT_OK) {
+                int count = mChannelDataManager.getChannelCountForInput(mInputIdUnderSetup);
+                String text;
+                if (count > 0) {
+                    text = getResources().getQuantityString(R.plurals.msg_channel_added,
+                            count, count);
                 } else {
-                    mInputIdUnderSetup = null;
+                    text = getString(R.string.msg_no_channel_added);
                 }
-                if (!mIsSetupActivityCalledByPopup) {
-                    mOverlayManager.getSideFragmentManager().showSidePanel(false);
+                Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
+                mInputIdUnderSetup = null;
+                if (mChannelTuner.getCurrentChannel() == null) {
+                    mChannelTuner.moveToAdjacentBrowsableChannel(true);
                 }
-                break;
-            case REQUEST_CODE_START_SYSTEM_CAPTIONING_SETTINGS:
+                if (mTunePending) {
+                    tune(true);
+                }
+            } else {
+                mInputIdUnderSetup = null;
+            }
+            if (!mIsSetupActivityCalledByPopup) {
                 mOverlayManager.getSideFragmentManager().showSidePanel(false);
-                break;
+            }
         }
         if (data != null) {
             String errorMessage = data.getStringExtra(LauncherActivity.ERROR_MESSAGE);
@@ -1418,18 +1319,12 @@
             // while gamepads support DPAD_CENTER and BACK by fallback.
             // Since we don't expect that TIS want to handle gamepad buttons now,
             // blacklist gamepad buttons and wait for next fallback keys.
-            // TODO) Need to consider other fallback keys (e.g. ESCAPE)
+            // TODO: Need to consider other fallback keys (e.g. ESCAPE)
             return super.dispatchKeyEvent(event);
         }
         return dispatchKeyEventToSession(event) || super.dispatchKeyEvent(event);
     }
 
-    @Override
-    public void onAudioFocusChange(int focusChange) {
-        mAudioFocusStatus = focusChange;
-        setVolumeByAudioFocusStatus();
-    }
-
     /**
      * Notifies the key input focus is changed to the TV view.
      */
@@ -1449,18 +1344,6 @@
         if (!mTvView.isPlaying()) {
             mCaptionSettings = new CaptionSettings(this);
         }
-
-        // Handle the passed key press, if any. Note that only the key codes that are currently
-        // handled in the TV app will be handled via Intent.
-        // TODO: Consider defining a separate intent filter as passing data of mime type
-        // vnd.android.cursor.item/channel isn't really necessary here.
-        int keyCode = intent.getIntExtra(Utils.EXTRA_KEY_KEYCODE, KeyEvent.KEYCODE_UNKNOWN);
-        if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
-            if (DEBUG) Log.d(TAG, "Got an intent with keycode: " + keyCode);
-            KeyEvent event = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
-            onKeyUp(keyCode, event);
-            return true;
-        }
         mShouldTuneToTunerChannel = intent.getBooleanExtra(Utils.EXTRA_KEY_FROM_LAUNCHER, false);
         mInitChannelUri = null;
 
@@ -1476,9 +1359,6 @@
             }
         }
 
-        // TODO: remove the checkState once N API is finalized.
-        SoftPreconditions.checkState(TvInputManager.ACTION_SETUP_INPUTS.equals(
-                "android.media.tv.action.SETUP_INPUTS"));
         if (TvInputManager.ACTION_SETUP_INPUTS.equals(intent.getAction())) {
             runAfterAttachedToWindow(new Runnable() {
                 @Override
@@ -1488,17 +1368,12 @@
             });
         } else if (Intent.ACTION_VIEW.equals(intent.getAction())) {
             Uri uri = intent.getData();
-            try {
-                mSource = uri.getQueryParameter(Utils.PARAM_SOURCE);
-            } catch (UnsupportedOperationException e) {
-                // ignore this exception.
-            }
-            // When the URI points to the programs (directory, not an individual item), go to the
-            // program guide. The intention here is to respond to
-            // "content://android.media.tv/program", not "content://android.media.tv/program/XXX".
-            // Later, we might want to add handling of individual programs too.
             if (Utils.isProgramsUri(uri)) {
-                // The given data is a programs URI. Open the Program Guide.
+                // When the URI points to the programs (directory, not an individual item), go to
+                // the program guide. The intention here is to respond to
+                // "content://android.media.tv/program", not
+                // "content://android.media.tv/program/XXX".
+                // Later, we might want to add handling of individual programs too.
                 mShowProgramGuide = true;
                 return true;
             }
@@ -1541,17 +1416,19 @@
                 }
             } else if (mInitChannelUri != null) {
                 // Handle the URI built by TvContract.buildChannelsUriForInput().
-                // TODO: Change hard-coded "input" to TvContract.PARAM_INPUT.
                 String inputId = mInitChannelUri.getQueryParameter("input");
                 long channelId = Utils.getLastWatchedChannelIdForInput(this, inputId);
                 if (channelId == Channel.INVALID_ID) {
                     String[] projection = { Channels._ID };
+                    long time = System.currentTimeMillis();
                     try (Cursor cursor = getContentResolver().query(uri, projection,
                             null, null, null)) {
                         if (cursor != null && cursor.moveToNext()) {
                             channelId = cursor.getLong(0);
                         }
                     }
+                    Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity queries DB for "
+                            + "last channel check (" + (System.currentTimeMillis() - time) + "ms)");
                 }
                 if (channelId == Channel.INVALID_ID) {
                     // Couldn't find any channel probably because the input hasn't been set up.
@@ -1567,41 +1444,6 @@
         return true;
     }
 
-    private void setVolumeByAudioFocusStatus() {
-        if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
-            setVolumeByAudioFocusStatus(mTvView);
-        } else { // mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW
-            setVolumeByAudioFocusStatus(mPipView);
-        }
-    }
-
-    private void setVolumeByAudioFocusStatus(TunableTvView tvView) {
-        SoftPreconditions.checkState(tvView == mTvView || tvView == mPipView);
-        if (tvView.isPlaying()) {
-            switch (mAudioFocusStatus) {
-                case AudioManager.AUDIOFOCUS_GAIN:
-                    tvView.setStreamVolume(AUDIO_MAX_VOLUME);
-                    break;
-                case AudioManager.AUDIOFOCUS_LOSS:
-                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
-                    tvView.setStreamVolume(AUDIO_MIN_VOLUME);
-                    break;
-                case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
-                    tvView.setStreamVolume(AUDIO_DUCKING_VOLUME);
-                    break;
-            }
-        }
-        if (tvView == mTvView) {
-            if (mPipView != null && mPipView.isPlaying()) {
-                mPipView.setStreamVolume(AUDIO_MIN_VOLUME);
-            }
-        } else {  // tvView == mPipView
-            if (mTvView != null && mTvView.isPlaying()) {
-                mTvView.setStreamVolume(AUDIO_MIN_VOLUME);
-            }
-        }
-    }
-
     private void stopTv() {
         stopTv(null, false);
     }
@@ -1617,10 +1459,8 @@
             if (!keepVisibleBehind) {
                 requestVisibleBehind(false);
             }
-            mAudioManager.abandonAudioFocus(this);
-            if (mMediaSession.isActive()) {
-                mMediaSession.setActive(false);
-            }
+            mAudioManagerHelper.abandonAudioFocus();
+            mMediaSessionWrapper.setPlaybackState(false);
         }
         TvApplication.getSingletons(this).getMainActivityWrapper()
                 .notifyCurrentChannelChange(this, null);
@@ -1628,99 +1468,11 @@
         mTunePending = false;
     }
 
-    private boolean isPlaying() {
-        return mTvView.isPlaying() && mTvView.getCurrentChannel() != null;
-    }
-
-    private void startPip(final boolean fromUserInteraction) {
-        if (mPipChannel == null) {
-            Log.w(TAG, "PIP channel id is an invalid id.");
-            return;
-        }
-        if (DEBUG) Log.d(TAG, "startPip() " + mPipChannel);
-        mPipView.start(mTvInputManagerHelper);
-        boolean success = mPipView.tuneTo(mPipChannel, null, new OnTuneListener() {
-            @Override
-            public void onUnexpectedStop(Channel channel) {
-                Log.w(TAG, "The PIP is Unexpectedly stopped");
-                enablePipView(false, false);
-            }
-
-            @Override
-            public void onTuneFailed(Channel channel) {
-                Log.w(TAG, "Fail to start the PIP during channel tuning");
-                if (fromUserInteraction) {
-                    Toast.makeText(MainActivity.this, R.string.msg_no_pip_support,
-                            Toast.LENGTH_SHORT).show();
-                    enablePipView(false, false);
-                }
-            }
-
-            @Override
-            public void onStreamInfoChanged(StreamInfo info) {
-                mTvViewUiManager.updatePipView();
-                mHandler.removeCallbacks(mRestoreMainViewRunnable);
-                restoreMainTvView();
-            }
-
-            @Override
-            public void onChannelRetuned(Uri channel) {
-                if (channel == null) {
-                    return;
-                }
-                Channel currentChannel =
-                        mChannelDataManager.getChannel(ContentUris.parseId(channel));
-                if (currentChannel == null) {
-                    Log.e(TAG, "onChannelRetuned is called from PIP input but can't find a channel"
-                            + " with the URI " + channel);
-                    return;
-                }
-                if (isChannelChangeKeyDownReceived()) {
-                    // Ignore this message if the user is changing the channel.
-                    return;
-                }
-                mPipChannel = currentChannel;
-                mPipView.setCurrentChannel(mPipChannel);
-            }
-
-            @Override
-            public void onContentBlocked() {
-                updateMediaSession();
-            }
-
-            @Override
-            public void onContentAllowed() {
-                updateMediaSession();
-            }
-        });
-        if (!success) {
-            Log.w(TAG, "Fail to start the PIP");
-            return;
-        }
-        if (fromUserInteraction) {
-            checkChannelLockNeeded(mPipView);
-        }
-        // Explicitly make the PIP view main to make the selected input an HDMI-CEC active source.
-        mPipView.setMain();
-        scheduleRestoreMainTvView();
-        mTvViewUiManager.onPipStart();
-        setVolumeByAudioFocusStatus();
-    }
-
     private void scheduleRestoreMainTvView() {
         mHandler.removeCallbacks(mRestoreMainViewRunnable);
         mHandler.postDelayed(mRestoreMainViewRunnable, TVVIEW_SET_MAIN_TIMEOUT_MS);
     }
 
-    private void stopPip() {
-        if (DEBUG) Log.d(TAG, "stopPip");
-        if (mPipView.isPlaying()) {
-            mPipView.stop();
-            mPipSwap = false;
-            mTvViewUiManager.onPipStop();
-        }
-    }
-
     /**
      * Says {@code text} when accessibility is turned on.
      */
@@ -1735,7 +1487,7 @@
         }
     }
 
-    private void tune() {
+    private void tune(boolean updateChannelBanner) {
         if (DEBUG) Log.d(TAG, "tune()");
         mTuneDurationTimer.start();
 
@@ -1748,6 +1500,10 @@
         }
         mTunePending = false;
         final Channel channel = mChannelTuner.getCurrentChannel();
+        SoftPreconditions.checkState(channel != null);
+        if (channel == null) {
+            return;
+        }
         if (!mChannelTuner.isCurrentChannelPassthrough()) {
             if (mTvInputManagerHelper.getTunerTvInputSize() == 0) {
                 Toast.makeText(this, R.string.msg_no_input, Toast.LENGTH_SHORT).show();
@@ -1763,8 +1519,26 @@
                 }
                 if (mChannelDataManager.getChannelCount() > 0) {
                     mOverlayManager.showIntroDialog();
+                } else {
+                    startOnboardingActivity();
+                    return;
                 }
             }
+            mShowNewSourcesFragment = false;
+            if (mChannelTuner.getBrowsableChannelCount() == 0
+                    && mChannelDataManager.getChannelCount() > 0
+                    && !mOverlayManager.getSideFragmentManager().isActive()) {
+                if (!mChannelTuner.areAllChannelsLoaded()) {
+                    return;
+                }
+                if (mTvInputManagerHelper.getTunerTvInputSize() == 1) {
+                    mOverlayManager.getSideFragmentManager().show(
+                            new CustomizeChannelListFragment());
+                } else {
+                    mOverlayManager.showSetupFragment();
+                }
+                return;
+            }
             if (!TvCommonUtils.isRunningInTest() && mShowNewSourcesFragment
                     && setupUtils.hasUnrecognizedInput(mTvInputManagerHelper)) {
                 // Show new channel sources fragment.
@@ -1780,36 +1554,6 @@
                     }
                 });
             }
-            mShowNewSourcesFragment = false;
-            if (mChannelTuner.getBrowsableChannelCount() == 0
-                    && mChannelDataManager.getChannelCount() > 0
-                    && !mOverlayManager.getSideFragmentManager().isActive()) {
-                if (!mChannelTuner.areAllChannelsLoaded()) {
-                    return;
-                }
-                if (mTvInputManagerHelper.getTunerTvInputSize() == 1) {
-                    mOverlayManager.getSideFragmentManager().show(
-                            new CustomizeChannelListFragment());
-                } else {
-                    showSettingsFragment();
-                }
-                return;
-            }
-            // TODO: need to refactor the following code to put in startTv.
-            if (channel == null) {
-                // There is no channel to tune to.
-                stopTv("tune()", false);
-                if (!mChannelDataManager.isDbLoadFinished()) {
-                    // Wait until channel data is loaded in order to know the number of channels.
-                    // tune() will be retried, once the channel data is loaded.
-                    return;
-                }
-                if (mOverlayManager.getSideFragmentManager().isActive()) {
-                    return;
-                }
-                mOverlayManager.showSetupFragment();
-                return;
-            }
             setupUtils.onTuned();
             if (mTuneParams != null) {
                 Long initChannelId = mTuneParams.getLong(KEY_INIT_CHANNEL_ID);
@@ -1825,7 +1569,6 @@
         if (!isUnderShrunkenTvView()) {
             mLastAllowedRatingForCurrentChannel = null;
         }
-        mHandler.removeMessages(MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE);
         // For every tune, we need to inform the tuned channel or input to a user,
         // if Talkback is turned on.
         sendAccessibilityText(!mChannelTuner.isCurrentChannelPassthrough() ?
@@ -1852,15 +1595,21 @@
             TvApplication.getSingletons(this).getMainActivityWrapper()
                     .notifyCurrentChannelChange(this, channel);
         }
-        checkChannelLockNeeded(mTvView);
-        updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_TUNE);
+        // We have to provide channel here instead of using TvView's channel, because TvView's
+        // channel might be null when there's tuner conflict. In that case, TvView will resets
+        // its current channel onConnectionFailed().
+        checkChannelLockNeeded(mTvView, channel);
+        if (updateChannelBanner) {
+            mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                    TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE);
+        }
         if (mActivityResumed) {
             // requestVisibleBehind should be called after onResume() is called. But, when
             // launcher is over the TV app and the screen is turned off and on, tune() can
             // be called during the pause state by mBroadcastReceiver (Intent.ACTION_SCREEN_ON).
             requestVisibleBehind(true);
         }
-        updateMediaSession();
+        mMediaSessionWrapper.update(mTvView.isBlocked(), getCurrentChannel(), getCurrentProgram());
     }
 
     // Runs the runnable after the activity is attached to window to show the fragment transition
@@ -1895,136 +1644,11 @@
         }
     }
 
-    private void updateMediaSession() {
-        if (getCurrentChannel() == null) {
-            mMediaSession.setActive(false);
-            return;
-        }
-
-        // If the channel is blocked, display a lock and a short text on the Now Playing Card
-        if (mTvView.isScreenBlocked() || mTvView.getBlockedContentRating() != null) {
-            setMediaSessionPlaybackState(false);
-
-            Bitmap art = BitmapFactory.decodeResource(
-                    getResources(), R.drawable.ic_message_lock_preview);
-            updateMediaMetadata(
-                    getResources().getString(R.string.channel_banner_locked_channel_title), art);
-            mMediaSession.setActive(true);
-            return;
-        }
-
-        final Program currentProgram = getCurrentProgram();
-        String cardTitleText = null;
-        String posterArtUri = null;
-        if (currentProgram != null) {
-            cardTitleText = currentProgram.getTitle();
-            posterArtUri = currentProgram.getPosterArtUri();
-        }
-        if (TextUtils.isEmpty(cardTitleText)) {
-            cardTitleText = getCurrentChannelName();
-        }
-        updateMediaMetadata(cardTitleText, null);
-        setMediaSessionPlaybackState(true);
-
-        if (posterArtUri == null) {
-            posterArtUri = TvContract.buildChannelLogoUri(getCurrentChannelId()).toString();
-        }
-        updatePosterArt(getCurrentChannel(), currentProgram, cardTitleText, null, posterArtUri);
-        mMediaSession.setActive(true);
-    }
-
-    private void updatePosterArt(Channel currentChannel, Program currentProgram,
-            String cardTitleText, @Nullable Bitmap posterArt, @Nullable String posterArtUri) {
-        if (posterArt != null) {
-            updateMediaMetadata(cardTitleText, posterArt);
-        } else if (posterArtUri != null) {
-            ImageLoader.loadBitmap(this, posterArtUri, mNowPlayingCardWidth, mNowPlayingCardHeight,
-                    new ProgramPosterArtCallback(this, currentChannel,
-                            currentProgram, cardTitleText));
-        } else {
-            updateMediaMetadata(cardTitleText, R.drawable.default_now_card);
-        }
-    }
-
-    private static class ProgramPosterArtCallback extends
-            ImageLoader.ImageLoaderCallback<MainActivity> {
-        private final Channel mChannel;
-        private final Program mProgram;
-        private final String mCardTitleText;
-
-        public ProgramPosterArtCallback(MainActivity mainActivity, Channel channel, Program program,
-                String cardTitleText) {
-            super(mainActivity);
-            mChannel = channel;
-            mProgram = program;
-            mCardTitleText = cardTitleText;
-        }
-
-        @Override
-        public void onBitmapLoaded(MainActivity mainActivity, @Nullable Bitmap posterArt) {
-            if (mainActivity.isNowPlayingProgram(mChannel, mProgram)) {
-                mainActivity.updatePosterArt(mChannel, mProgram, mCardTitleText, posterArt, null);
-            }
-        }
-    }
-
-    private boolean isNowPlayingProgram(Channel channel, Program program) {
+    boolean isNowPlayingProgram(Channel channel, Program program) {
         return program == null ? (channel != null && getCurrentProgram() == null
                 && channel.equals(getCurrentChannel())) : program.equals(getCurrentProgram());
     }
 
-    private void updateMediaMetadata(final String title, final Bitmap posterArt) {
-        new AsyncTask<Void, Void, Void> () {
-            @Override
-            protected Void doInBackground(Void... arg0) {
-                MediaMetadata.Builder builder = new MediaMetadata.Builder();
-                builder.putString(MediaMetadata.METADATA_KEY_TITLE, title);
-                if (posterArt != null) {
-                    builder.putBitmap(MediaMetadata.METADATA_KEY_ART, posterArt);
-                }
-                mMediaSession.setMetadata(builder.build());
-                return null;
-            }
-        }.execute();
-    }
-
-    private void updateMediaMetadata(final String title, final int imageResId) {
-        new AsyncTask<Void, Void, Void> () {
-            @Override
-            protected Void doInBackground(Void... arg0) {
-                MediaMetadata.Builder builder = new MediaMetadata.Builder();
-                builder.putString(MediaMetadata.METADATA_KEY_TITLE, title);
-                Bitmap posterArt = BitmapFactory.decodeResource(getResources(), imageResId);
-                if (posterArt != null) {
-                    builder.putBitmap(MediaMetadata.METADATA_KEY_ART, posterArt);
-                }
-                mMediaSession.setMetadata(builder.build());
-                return null;
-            }
-        }.execute();
-    }
-
-    private String getCurrentChannelName() {
-        Channel channel = getCurrentChannel();
-        if (channel == null) {
-            return "";
-        }
-        if (channel.isPassthrough()) {
-            TvInputInfo input = getTvInputManagerHelper().getTvInputInfo(channel.getInputId());
-            return Utils.loadLabel(this, input);
-        } else {
-            return channel.getDisplayName();
-        }
-    }
-
-    private void setMediaSessionPlaybackState(boolean isPlaying) {
-        PlaybackState.Builder builder = new PlaybackState.Builder();
-        builder.setState(isPlaying ? PlaybackState.STATE_PLAYING : PlaybackState.STATE_STOPPED,
-                PlaybackState.PLAYBACK_POSITION_UNKNOWN,
-                isPlaying ? MEDIA_SESSION_PLAYING_SPEED : MEDIA_SESSION_STOPPED_SPEED);
-        mMediaSession.setPlaybackState(builder.build());
-    }
-
     private void addToRecentChannels(long channelId) {
         if (!mRecentChannels.remove(channelId)) {
             if (mRecentChannels.size() >= MAX_RECENT_CHANNELS) {
@@ -2042,105 +1666,34 @@
         return mRecentChannels;
     }
 
-    private void checkChannelLockNeeded(TunableTvView tvView) {
-        Channel channel = tvView.getCurrentChannel();
-        if (tvView.isPlaying() && channel != null) {
+    private void checkChannelLockNeeded(TunableTvView tvView, Channel currentChannel) {
+        if (currentChannel == null) {
+            currentChannel = tvView.getCurrentChannel();
+        }
+        if (tvView.isPlaying() && currentChannel != null) {
             if (getParentalControlSettings().isParentalControlsEnabled()
-                    && channel.isLocked()
+                    && currentChannel.isLocked()
                     && !mShowLockedChannelsTemporarily
                     && !(isUnderShrunkenTvView()
-                            && channel.equals(mChannelBeforeShrunkenTvView)
+                            && currentChannel.equals(mChannelBeforeShrunkenTvView)
                             && mWasChannelUnblockedBeforeShrunkenByUser)) {
-                if (DEBUG) Log.d(TAG, "Channel " + channel.getId() + " is locked");
-                blockScreen(tvView);
+                if (DEBUG) Log.d(TAG, "Channel " + currentChannel.getId() + " is locked");
+                blockOrUnblockScreen(tvView, true);
             } else {
-                unblockScreen(tvView);
+                blockOrUnblockScreen(tvView, false);
             }
         }
     }
 
-    private void blockScreen(TunableTvView tvView) {
-        tvView.blockScreen();
+    private void blockOrUnblockScreen(TunableTvView tvView, boolean blockOrUnblock) {
+        tvView.blockOrUnblockScreen(blockOrUnblock);
         if (tvView == mTvView) {
-            updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
-            updateMediaSession();
+            mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                    TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
+            mMediaSessionWrapper.update(blockOrUnblock, getCurrentChannel(), getCurrentProgram());
         }
     }
 
-    private void unblockScreen(TunableTvView tvView) {
-        tvView.unblockScreen();
-        if (tvView == mTvView) {
-            updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
-            updateMediaSession();
-        }
-    }
-
-    /**
-     * Shows the channel banner if it was hidden from the side fragment.
-     *
-     * <p>When the side fragment is visible, showing the channel banner should be put off until the
-     * side fragment is closed even though the channel changes.
-     */
-    public void showChannelBannerIfHiddenBySideFragment() {
-        if (mChannelBannerHiddenBySideFragment) {
-            updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
-        }
-    }
-
-    private void updateChannelBannerAndShowIfNeeded(@ChannelBannerUpdateReason int reason) {
-        if(DEBUG) Log.d(TAG, "updateChannelBannerAndShowIfNeeded(reason=" + reason + ")");
-        if (!mChannelTuner.isCurrentChannelPassthrough()) {
-            int lockType = ChannelBannerView.LOCK_NONE;
-            if (mTvView.isScreenBlocked()) {
-                lockType = ChannelBannerView.LOCK_CHANNEL_INFO;
-            } else if (mTvView.getBlockedContentRating() != null
-                    || (getParentalControlSettings().isParentalControlsEnabled()
-                            && !mTvView.isVideoAvailable())) {
-                // If the parental control is enabled, do not show the program detail until the
-                // video becomes available.
-                lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
-            }
-            if (lockType == ChannelBannerView.LOCK_NONE) {
-                if (reason == UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST) {
-                    // Do not show detailed program information while fast-tuning.
-                    lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
-                } else if (reason == UPDATE_CHANNEL_BANNER_REASON_TUNE
-                        && getParentalControlSettings().isParentalControlsEnabled()) {
-                    // If parental control is turned on,
-                    // assumes that program is locked by default and waits for onContentAllowed.
-                    lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
-                }
-            }
-            // If lock type is not changed, we don't need to update channel banner by parental
-            // control.
-            if (!mChannelBannerView.setLockType(lockType)
-                    && reason == UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK) {
-                return;
-            }
-
-            mChannelBannerView.updateViews(mTvView);
-        }
-        boolean needToShowBanner = (reason == UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW
-                || reason == UPDATE_CHANNEL_BANNER_REASON_TUNE
-                || reason == UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST);
-        boolean noOverlayUiWhenResume =
-                mInputToSetUp == null && !mShowProgramGuide && !mShowSelectInputView;
-        if (needToShowBanner && noOverlayUiWhenResume
-                && mOverlayManager.getCurrentDialog() == null
-                && !mOverlayManager.isSetupFragmentActive()
-                && !mOverlayManager.isNewSourcesFragmentActive()) {
-            if (mChannelTuner.getCurrentChannel() == null) {
-                mChannelBannerHiddenBySideFragment = false;
-            } else if (mOverlayManager.getSideFragmentManager().isActive()) {
-                mChannelBannerHiddenBySideFragment = true;
-            } else {
-                mChannelBannerHiddenBySideFragment = false;
-                mOverlayManager.showBanner();
-            }
-        }
-        updateAvailabilityToast();
-    }
-
     /**
      * Hide the overlays when tuning to a channel from the menu (e.g. Channels).
      */
@@ -2197,7 +1750,7 @@
         if (bestTrack != null) {
             String selectedTrack = getSelectedTrack(TvTrackInfo.TYPE_AUDIO);
             if (!bestTrack.getId().equals(selectedTrack)) {
-                selectTrack(TvTrackInfo.TYPE_AUDIO, bestTrack);
+                selectTrack(TvTrackInfo.TYPE_AUDIO, bestTrack, UNDEFINED_TRACK_INDEX);
             } else {
                 mTvOptionsManager.onMultiAudioChanged(
                         Utils.getMultiAudioString(this, bestTrack, false));
@@ -2210,7 +1763,7 @@
     private void applyClosedCaption() {
         List<TvTrackInfo> tracks = getTracks(TvTrackInfo.TYPE_SUBTITLE);
         if (tracks == null) {
-            mTvOptionsManager.onClosedCaptionsChanged(null);
+            mTvOptionsManager.onClosedCaptionsChanged(null, UNDEFINED_TRACK_INDEX);
             return;
         }
 
@@ -2219,17 +1772,19 @@
 
         String selectedTrackId = getSelectedTrack(TvTrackInfo.TYPE_SUBTITLE);
         TvTrackInfo alternativeTrack = null;
+        int alternativeTrackIndex = UNDEFINED_TRACK_INDEX;
         if (enabled) {
             String language = mCaptionSettings.getLanguage();
             String trackId = mCaptionSettings.getTrackId();
-            for (TvTrackInfo track : tracks) {
+            for (int i = 0; i < tracks.size(); i++) {
+                TvTrackInfo track = tracks.get(i);
                 if (Utils.isEqualLanguage(track.getLanguage(), language)) {
                     if (track.getId().equals(trackId)) {
                         if (!track.getId().equals(selectedTrackId)) {
-                            selectTrack(TvTrackInfo.TYPE_SUBTITLE, track);
+                            selectTrack(TvTrackInfo.TYPE_SUBTITLE, track, i);
                         } else {
                             // Already selected. Update the option string only.
-                            mTvOptionsManager.onClosedCaptionsChanged(track);
+                            mTvOptionsManager.onClosedCaptionsChanged(track, i);
                         }
                         if (DEBUG) {
                             Log.d(TAG, "Subtitle Track Selected {id=" + track.getId()
@@ -2238,14 +1793,16 @@
                         return;
                     } else if (alternativeTrack == null) {
                         alternativeTrack = track;
+                        alternativeTrackIndex = i;
                     }
                 }
             }
             if (alternativeTrack != null) {
                 if (!alternativeTrack.getId().equals(selectedTrackId)) {
-                    selectTrack(TvTrackInfo.TYPE_SUBTITLE, alternativeTrack);
+                    selectTrack(TvTrackInfo.TYPE_SUBTITLE, alternativeTrack, alternativeTrackIndex);
                 } else {
-                    mTvOptionsManager.onClosedCaptionsChanged(alternativeTrack);
+                    mTvOptionsManager
+                            .onClosedCaptionsChanged(alternativeTrack, alternativeTrackIndex);
                 }
                 if (DEBUG) {
                     Log.d(TAG, "Subtitle Track Selected {id=" + alternativeTrack.getId()
@@ -2255,29 +1812,11 @@
             }
         }
         if (selectedTrackId != null) {
-            selectTrack(TvTrackInfo.TYPE_SUBTITLE, null);
+            selectTrack(TvTrackInfo.TYPE_SUBTITLE, null, UNDEFINED_TRACK_INDEX);
             if (DEBUG) Log.d(TAG, "Subtitle Track Unselected");
             return;
         }
-        mTvOptionsManager.onClosedCaptionsChanged(null);
-    }
-
-    /**
-     * Pops up the KeypadChannelSwitchView with the given key input event.
-     *
-     * @param keyCode A key code of the key event.
-     */
-    public void showKeypadChannelSwitchView(int keyCode) {
-        if (mChannelTuner.areAllChannelsLoaded()) {
-            mOverlayManager.showKeypadChannelSwitch();
-            mKeypadChannelSwitchView.onNumberKeyUp(keyCode - KeyEvent.KEYCODE_0);
-        }
-    }
-
-    public void showSearchActivity() {
-        // HACK: Once we moved the window layer to TYPE_APPLICATION_SUB_PANEL,
-        // the voice button doesn't work. So we directly call the voice action.
-        SearchManagerHelper.getInstance(this).launchAssistAction();
+        mTvOptionsManager.onClosedCaptionsChanged(null, UNDEFINED_TRACK_INDEX);
     }
 
     public void showProgramGuideSearchFragment() {
@@ -2295,13 +1834,12 @@
     @Override
     protected void onDestroy() {
         if (DEBUG) Log.d(TAG, "onDestroy()");
-        SideFragment.releasePreloadedRecycledViews();
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).reset();
+        SideFragment.releaseRecycledViewPool();
+        ViewCache.getInstance().clear();
         if (mTvView != null) {
             mTvView.release();
         }
-        if (mPipView != null) {
-            mPipView.release();
-        }
         if (mChannelTuner != null) {
             mChannelTuner.removeListener(mChannelTunerListener);
             mChannelTuner.stop();
@@ -2314,21 +1852,15 @@
                 mProgramDataManager.setPrefetchEnabled(false);
             }
         }
-        if (mPipInputManager != null) {
-            mPipInputManager.stop();
-        }
         if (mOverlayManager != null) {
             mOverlayManager.release();
         }
-        if (mKeypadChannelSwitchView != null) {
-            mKeypadChannelSwitchView.setChannels(null);
-        }
         mMemoryManageables.clear();
-        if (mMediaSession != null) {
-            mMediaSession.release();
+        if (mMediaSessionWrapper != null) {
+            mMediaSessionWrapper.release();
         }
-        if (mAudioCapabilitiesReceiver != null) {
-            mAudioCapabilitiesReceiver.unregister();
+        if (mAudioManagerHelper != null) {
+            mAudioManagerHelper.release();
         }
         mHandler.removeCallbacksAndMessages(null);
         application.getMainActivityWrapper().onMainActivityDestroyed(this);
@@ -2340,8 +1872,11 @@
             mChannelStatusRecurringRunner.stop();
             mChannelStatusRecurringRunner = null;
         }
-        if (mTvInputManagerHelper != null && Features.TUNER.isEnabled(this)) {
-            mTvInputManagerHelper.removeCallback(mTvInputCallback);
+        if (mTvInputManagerHelper != null) {
+            mTvInputManagerHelper.clearTvInputLabels();
+            if (Features.TUNER.isEnabled(this)) {
+                mTvInputManagerHelper.removeCallback(mTvInputCallback);
+            }
         }
         super.onDestroy();
     }
@@ -2410,7 +1945,6 @@
          *  G debug: refresh cloud epg
          *  I KEYCODE_TV_INPUT
          *  O debug: show display mode option
-         *  P debug: togglePipView
          *  S KEYCODE_CAPTIONS: select subtitle
          *  W debug: toggle screen size
          *  V KEYCODE_MEDIA_RECORD debug: record the current channel for 30 sec
@@ -2422,8 +1956,9 @@
         finishChannelChangeIfNeeded();
 
         if (event.getKeyCode() == KeyEvent.KEYCODE_SEARCH) {
-            showSearchActivity();
-            return true;
+            // Prevent MainActivity from being closed by onVisibleBehindCanceled()
+            mOtherActivityLaunched = true;
+            return false;
         }
         switch (mOverlayManager.onKeyUp(keyCode, event)) {
             case KEY_EVENT_HANDLER_RESULT_DISPATCH_TO_OVERLAY:
@@ -2467,12 +2002,12 @@
             }
         } else {
             if (KeypadChannelSwitchView.isChannelNumberKey(keyCode)) {
-                showKeypadChannelSwitchView(keyCode);
+                mOverlayManager.showKeypadChannelSwitch(keyCode);
                 return true;
             }
             switch (keyCode) {
                 case KeyEvent.KEYCODE_DPAD_RIGHT:
-                    if (!mTvView.isVideoAvailable()
+                    if (!mTvView.isVideoOrAudioAvailable()
                             && mTvView.getVideoUnavailableReason()
                             == TunableTvView.VIDEO_UNAVAILABLE_REASON_NO_RESOURCE) {
                         DvrUiHelper.startSchedulesActivityForTuneConflict(this,
@@ -2480,35 +2015,16 @@
                         return true;
                     }
                     if (!PermissionUtils.hasModifyParentalControls(this)) {
-                        // TODO: support this feature for non-system LC app. b/23939816
                         return true;
                     }
                     PinDialogFragment dialog = null;
                     if (mTvView.isScreenBlocked()) {
-                        dialog = new PinDialogFragment(
-                                PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_CHANNEL,
-                                new PinDialogFragment.ResultListener() {
-                                    @Override
-                                    public void done(boolean success) {
-                                        if (success) {
-                                            unblockScreen(mTvView);
-                                            mIsCurrentChannelUnblockedByUser = true;
-                                        }
-                                    }
-                                });
-                    } else if (mTvView.getBlockedContentRating() != null) {
-                        final TvContentRating rating = mTvView.getBlockedContentRating();
-                        dialog = new PinDialogFragment(
-                                PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM,
-                                new PinDialogFragment.ResultListener() {
-                                    @Override
-                                    public void done(boolean success) {
-                                        if (success) {
-                                            mLastAllowedRatingForCurrentChannel = rating;
-                                            mTvView.unblockContent(rating);
-                                        }
-                                    }
-                                });
+                        dialog = PinDialogFragment
+                                .create(PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_CHANNEL);
+                    } else if (mTvView.isContentBlocked()) {
+                        dialog = PinDialogFragment
+                                .create(PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM,
+                                        mTvView.getBlockedContentRating().flattenToString());
                     }
                     if (dialog != null) {
                         mOverlayManager.showDialogFragment(PinDialogFragment.DIALOG_TAG, dialog,
@@ -2531,7 +2047,8 @@
                         return true;
                     }
                     if (keyCode != KeyEvent.KEYCODE_MENU) {
-                        updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
+                        mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                                TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
                     }
                     if (keyCode != KeyEvent.KEYCODE_E) {
                         mOverlayManager.showMenu(Menu.REASON_NONE);
@@ -2547,6 +2064,7 @@
                     if (!SystemProperties.USE_DEBUG_KEYS.getValue()) {
                         break;
                     }
+                    // Pass through.
                 case KeyEvent.KEYCODE_CAPTIONS: {
                     mOverlayManager.getSideFragmentManager().show(new ClosedCaptionFragment());
                     return true;
@@ -2555,14 +2073,11 @@
                     if (!SystemProperties.USE_DEBUG_KEYS.getValue()) {
                         break;
                     }
+                    // Pass through.
                 case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
                     mOverlayManager.getSideFragmentManager().show(new MultiAudioFragment());
                     return true;
                 }
-                case KeyEvent.KEYCODE_GUIDE: {
-                    mOverlayManager.showProgramGuide();
-                    return true;
-                }
                 case KeyEvent.KEYCODE_INFO: {
                     mOverlayManager.showBanner();
                     return true;
@@ -2578,22 +2093,17 @@
                                 Toast.makeText(this, R.string.dvr_msg_cannot_record_program,
                                         Toast.LENGTH_SHORT).show();
                             } else {
-                                if (!DvrUiHelper.checkStorageStatusAndShowErrorMessage(this,
-                                        currentChannel.getInputId())) {
-                                    return true;
-                                }
                                 Program program = mProgramDataManager
                                         .getCurrentProgram(currentChannel.getId());
-                                if (program == null) {
-                                    DvrUiHelper
-                                            .showChannelRecordDurationOptions(this, currentChannel);
-                                } else if (DvrUiHelper.handleCreateSchedule(this, program)) {
-                                    String msg = getString(
-                                            R.string.dvr_msg_current_program_scheduled,
-                                            program.getTitle(), Utils.toTimeString(
-                                                    program.getEndTimeUtcMillis(), false));
-                                    Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
-                                }
+                                DvrUiHelper.checkStorageStatusAndShowErrorMessage(this,
+                                        currentChannel.getInputId(), new Runnable() {
+                                            @Override
+                                            public void run() {
+                                                DvrUiHelper.requestRecordingCurrentProgram(
+                                                        MainActivity.this,
+                                                        currentChannel, program, false);
+                                            }
+                                        });
                             }
                         } else {
                             DvrUiHelper.showStopRecordingDialog(this, currentChannel.getId(),
@@ -2624,7 +2134,7 @@
         }
         if (SystemProperties.USE_DEBUG_KEYS.getValue() || BuildConfig.ENG) {
             switch (keyCode) {
-                case KeyEvent.KEYCODE_W: {
+                case KeyEvent.KEYCODE_W:
                     mDebugNonFullSizeScreen = !mDebugNonFullSizeScreen;
                     if (mDebugNonFullSizeScreen) {
                         FrameLayout.LayoutParams params =
@@ -2632,30 +2142,23 @@
                         params.width = 960;
                         params.height = 540;
                         params.gravity = Gravity.START;
-                        mTvView.setLayoutParams(params);
+                        mTvView.setTvViewLayoutParams(params);
                     } else {
                         FrameLayout.LayoutParams params =
                                 (FrameLayout.LayoutParams) mTvView.getLayoutParams();
                         params.width = ViewGroup.LayoutParams.MATCH_PARENT;
                         params.height = ViewGroup.LayoutParams.MATCH_PARENT;
                         params.gravity = Gravity.CENTER;
-                        mTvView.setLayoutParams(params);
+                        mTvView.setTvViewLayoutParams(params);
                     }
                     return true;
-                }
-                case KeyEvent.KEYCODE_P: {
-                    togglePipView();
-                    return true;
-                }
                 case KeyEvent.KEYCODE_CTRL_LEFT:
-                case KeyEvent.KEYCODE_CTRL_RIGHT: {
+                case KeyEvent.KEYCODE_CTRL_RIGHT:
                     mUseKeycodeBlacklist = !mUseKeycodeBlacklist;
                     return true;
-                }
-                case KeyEvent.KEYCODE_O: {
+                case KeyEvent.KEYCODE_O:
                     mOverlayManager.getSideFragmentManager().show(new DisplayModeFragment());
                     return true;
-                }
                 case KeyEvent.KEYCODE_D:
                     mOverlayManager.getSideFragmentManager().show(new DeveloperOptionFragment());
                     return true;
@@ -2681,22 +2184,6 @@
     }
 
     @Override
-    public void onBackPressed() {
-        // The activity should be returned to the caller of this activity
-        // when the mSource is not null.
-        if (!mOverlayManager.getSideFragmentManager().isActive() && isPlaying()
-                && mSource == null) {
-            // If back key would exit TV app,
-            // show McLauncher instead so we can get benefit of McLauncher's shyMode.
-            Intent startMain = new Intent(Intent.ACTION_MAIN);
-            startMain.addCategory(Intent.CATEGORY_HOME);
-            startActivity(startMain);
-        } else {
-            super.onBackPressed();
-        }
-    }
-
-    @Override
     public void onUserInteraction() {
         super.onUserInteraction();
         if (mOverlayManager != null) {
@@ -2725,66 +2212,10 @@
         }
     }
 
-    public void togglePipView() {
-        enablePipView(!mPipEnabled, true);
-        mOverlayManager.getMenu().update();
-    }
-
-    public boolean isPipEnabled() {
-        return mPipEnabled;
-    }
-
-    public void tuneToChannelForPip(Channel channel) {
-        if (!mPipEnabled) {
-            throw new IllegalStateException("tuneToChannelForPip is called when PIP is off");
-        }
-        if (mPipChannel.equals(channel)) {
-            return;
-        }
-        mPipChannel = channel;
-        startPip(true);
-    }
-
-    private void enablePipView(boolean enable, boolean fromUserInteraction) {
-        if (enable == mPipEnabled) {
-            return;
-        }
-        if (enable) {
-            List<PipInput> pipAvailableInputs = mPipInputManager.getPipInputList(true);
-            if (pipAvailableInputs.isEmpty()) {
-                Toast.makeText(this, R.string.msg_no_available_input_by_pip, Toast.LENGTH_SHORT)
-                        .show();
-                return;
-            }
-            // TODO: choose the last pip input.
-            Channel pipChannel = pipAvailableInputs.get(0).getChannel();
-            if (pipChannel != null) {
-                mPipEnabled = true;
-                mPipChannel = pipChannel;
-                startPip(fromUserInteraction);
-                mTvViewUiManager.restorePipSize();
-                mTvViewUiManager.restorePipLayout();
-                mTvOptionsManager.onPipChanged(mPipEnabled);
-            } else {
-                Toast.makeText(this, R.string.msg_no_available_input_by_pip, Toast.LENGTH_SHORT)
-                        .show();
-            }
-        } else {
-            mPipEnabled = false;
-            mPipChannel = null;
-            // Recover the stream volume of the main TV view, if needed.
-            if (mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW) {
-                setVolumeByAudioFocusStatus(mTvView);
-                mPipSound = TvSettings.PIP_SOUND_MAIN;
-                mTvOptionsManager.onPipSoundChanged(mPipSound);
-            }
-            stopPip();
-            mTvViewUiManager.restoreDisplayMode(false);
-            mTvOptionsManager.onPipChanged(mPipEnabled);
-        }
-    }
-
-    private boolean isChannelChangeKeyDownReceived() {
+    /**
+     * Returns {@code true} if one of the channel changing keys are pressed and not released yet.
+     */
+    public boolean isChannelChangeKeyDownReceived() {
         return mHandler.hasMessages(MSG_CHANNEL_UP_PRESSED)
                 || mHandler.hasMessages(MSG_CHANNEL_DOWN_PRESSED);
     }
@@ -2811,10 +2242,6 @@
         if (SystemProperties.LOG_KEYEVENT.getValue()) {
             Log.d(TAG, "dispatchKeyEventToSession(" + event + ")");
         }
-        if (mPipEnabled && mChannelTuner.isCurrentChannelPassthrough()) {
-            // If PIP is enabled, key events will be used by UI.
-            return false;
-        }
         boolean handled = false;
         if (mTvView != null) {
             handled = mTvView.dispatchKeyEvent(event);
@@ -2832,21 +2259,15 @@
     }
 
     private boolean isKeyEventBlocked() {
-        // If the current channel is passthrough channel without a PIP view,
-        // we always don't handle the key events in TV activity. Instead, the key event will
-        // be handled by the passthrough TV input.
-        return mChannelTuner.isCurrentChannelPassthrough() && !mPipEnabled;
+        // If the current channel is a passthrough channel, we don't handle the key events in TV
+        // activity. Instead, the key event will be handled by the passthrough TV input.
+        return mChannelTuner.isCurrentChannelPassthrough();
     }
 
     private void tuneToLastWatchedChannelForTunerInput() {
         if (!mChannelTuner.isCurrentChannelPassthrough()) {
             return;
         }
-        if (mPipEnabled) {
-            if (!mPipChannel.isPassthrough()) {
-                enablePipView(false, true);
-            }
-        }
         stopTv();
         startTv(null);
     }
@@ -2857,16 +2278,17 @@
                 mTvView.reset();
             }
         } else {
-            if (mPipEnabled && mPipInputManager.areInSamePipInput(channel, mPipChannel)) {
-                enablePipView(false, true);
-            }
             if (!mTvView.isPlaying()) {
                 startTv(channel.getUri());
             } else if (channel.equals(mTvView.getCurrentChannel())) {
-                updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_TUNE);
+                mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                        TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE);
+            } else if (channel == mChannelTuner.getCurrentChannel()) {
+                // Channel banner is already updated in moveToAdjacentChannel
+                tune(false);
             } else if (mChannelTuner.moveToChannel(channel)) {
                 // Channel banner would be updated inside of tune.
-                tune();
+                tune(true);
             } else {
                 showSettingsFragment();
             }
@@ -2883,107 +2305,25 @@
      */
     private void moveToAdjacentChannel(boolean channelUp, boolean fastTuning) {
         if (mChannelTuner.moveToAdjacentBrowsableChannel(channelUp)) {
-            updateChannelBannerAndShowIfNeeded(fastTuning ? UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST
-                    : UPDATE_CHANNEL_BANNER_REASON_TUNE);
+            mOverlayManager.updateChannelBannerAndShowIfNeeded(fastTuning ?
+                    TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST
+                    : TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE);
         }
     }
 
-    public Channel getPipChannel() {
-        return mPipChannel;
-    }
-
-    /**
-     * Swap the main and the sub screens while in the PIP mode.
-     */
-    public void swapPip() {
-        if (!mPipEnabled || mTvView == null || mPipView == null) {
-            Log.e(TAG, "swapPip() - not in PIP");
-            mPipSwap = false;
-            return;
-        }
-
-        Channel channel = mTvView.getCurrentChannel();
-        boolean tvViewBlocked = mTvView.isScreenBlocked();
-        boolean pipViewBlocked = mPipView.isScreenBlocked();
-        if (channel == null || !mTvView.isPlaying()) {
-            // If the TV view is not currently playing or its current channel is null, swapping here
-            // basically means disabling the PIP mode and getting back to the full screen since
-            // there's no point of keeping a blank PIP screen at the bottom which is not tune-able.
-            enablePipView(false, true);
-            mOverlayManager.hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_DEFAULT);
-            mPipSwap = false;
-            return;
-        }
-
-        // Reset the TV view and tune the PIP view to the previous channel of the TV view.
-        mTvView.reset();
-        mPipView.reset();
-        Channel oldPipChannel = mPipChannel;
-        tuneToChannelForPip(channel);
-        if (tvViewBlocked) {
-            mPipView.blockScreen();
-        } else {
-            mPipView.unblockScreen();
-        }
-
-        if (oldPipChannel != null) {
-            // Tune the TV view to the previous PIP channel.
-            tuneToChannel(oldPipChannel);
-        }
-        if (pipViewBlocked) {
-            mTvView.blockScreen();
-        } else {
-            mTvView.unblockScreen();
-        }
-        if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
-            setVolumeByAudioFocusStatus(mTvView);
-        } else { // mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW
-            setVolumeByAudioFocusStatus(mPipView);
-        }
-        mPipSwap = !mPipSwap;
-        mTvOptionsManager.onPipSwapChanged(mPipSwap);
-    }
-
-    /**
-     * Toggle where the sound is coming from when the user is watching the PIP.
-     */
-    public void togglePipSoundMode() {
-        if (!mPipEnabled || mTvView == null || mPipView == null) {
-            Log.e(TAG, "togglePipSoundMode() - not in PIP");
-            return;
-        }
-        if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
-            setVolumeByAudioFocusStatus(mPipView);
-            mPipSound = TvSettings.PIP_SOUND_PIP_WINDOW;
-        } else { // mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW
-            setVolumeByAudioFocusStatus(mTvView);
-            mPipSound = TvSettings.PIP_SOUND_MAIN;
-        }
-        restoreMainTvView();
-        mTvOptionsManager.onPipSoundChanged(mPipSound);
-    }
-
     /**
      * Set the main TV view which holds HDMI-CEC active source based on the sound mode
      */
     private void restoreMainTvView() {
-        if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
-            mTvView.setMain();
-        } else { // mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW
-            mPipView.setMain();
-        }
+        mTvView.setMain();
     }
 
     @Override
     public void onVisibleBehindCanceled() {
         stopTv("onVisibleBehindCanceled()", false);
         mTracker.sendScreenView("");
-        mAudioFocusStatus = AudioManager.AUDIOFOCUS_LOSS;
-        mAudioManager.abandonAudioFocus(this);
-        if (mMediaSession.isActive()) {
-            mMediaSession.setActive(false);
-        }
-        stopPip();
+        mAudioManagerHelper.abandonAudioFocus();
+        mMediaSessionWrapper.setPlaybackState(false);
         mVisibleBehind = false;
         if (!mOtherActivityLaunched && Build.VERSION.SDK_INT == Build.VERSION_CODES.M) {
             // Workaround: in M, onStop is not called, even though it should be called after
@@ -3012,13 +2352,13 @@
         return mTvView.getSelectedTrack(type);
     }
 
-    private void selectTrack(int type, TvTrackInfo track) {
+    private void selectTrack(int type, TvTrackInfo track, int trackIndex) {
         mTvView.selectTrack(type, track == null ? null : track.getId());
         if (type == TvTrackInfo.TYPE_AUDIO) {
             mTvOptionsManager.onMultiAudioChanged(track == null ? null :
                     Utils.getMultiAudioString(this, track, false));
         } else if (type == TvTrackInfo.TYPE_SUBTITLE) {
-            mTvOptionsManager.onClosedCaptionsChanged(track);
+            mTvOptionsManager.onClosedCaptionsChanged(track, trackIndex);
         }
     }
 
@@ -3073,16 +2413,12 @@
     }
 
     private void updateAvailabilityToast() {
-        updateAvailabilityToast(mTvView);
-    }
-
-    private void updateAvailabilityToast(StreamInfo info) {
-        if (info.isVideoAvailable()) {
+        if (mTvView.isVideoAvailable()
+                || mTvView.getCurrentChannel() != mChannelTuner.getCurrentChannel()) {
             return;
         }
 
-        int stringId;
-        switch (info.getVideoUnavailableReason()) {
+        switch (mTvView.getVideoUnavailableReason()) {
             case TunableTvView.VIDEO_UNAVAILABLE_REASON_NOT_TUNED:
             case TunableTvView.VIDEO_UNAVAILABLE_REASON_NO_RESOURCE:
             case TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING:
@@ -3092,13 +2428,22 @@
                 return;
             case TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN:
             default:
-                stringId = R.string.msg_channel_unavailable_unknown;
+                Toast.makeText(this, R.string.msg_channel_unavailable_unknown,
+                        Toast.LENGTH_SHORT).show();
                 break;
         }
-
-        Toast.makeText(this, stringId, Toast.LENGTH_SHORT).show();
     }
 
+    /**
+     * Returns {@code true} if some overlay UI will be shown when the activity is resumed.
+     */
+    public boolean willShowOverlayUiWhenResume() {
+        return mInputToSetUp != null || mShowProgramGuide || mShowSelectInputView;
+    }
+
+    /**
+     * Returns the current parental control settings.
+     */
     public ParentalControlSettings getParentalControlSettings() {
         return mTvInputManagerHelper.getParentalControlSettings();
     }
@@ -3110,6 +2455,9 @@
         return mTvInputManagerHelper.getContentRatingsManager();
     }
 
+    /**
+     * Returns the current captioning settings.
+     */
     public CaptionSettings getCaptionSettings() {
         return mCaptionSettings;
     }
@@ -3163,6 +2511,7 @@
                 if (mActivityStarted) {
                     initAnimations();
                     initSideFragments();
+                    initMenuItemViews();
                 }
             }
         }, LAZY_INITIALIZATION_DELAY);
@@ -3174,7 +2523,11 @@
     }
 
     private void initSideFragments() {
-        SideFragment.preloadRecycledViews(this);
+        SideFragment.preloadItemViews(this);
+    }
+
+    private void initMenuItemViews() {
+        mOverlayManager.getMenu().preloadItemViews();
     }
 
     @Override
@@ -3207,10 +2560,6 @@
                     sendMessageDelayed(Message.obtain(msg), getDelay(startTime));
                     mainActivity.moveToAdjacentChannel(true, true);
                     break;
-                case MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE:
-                    mainActivity.updateChannelBannerAndShowIfNeeded(
-                            UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
-                    break;
             }
         }
 
@@ -3225,14 +2574,10 @@
     private class MyOnTuneListener implements OnTuneListener {
         boolean mUnlockAllowedRatingBeforeShrunken = true;
         boolean mWasUnderShrunkenTvView;
-        long mStreamInfoUpdateTimeThresholdMs;
         Channel mChannel;
 
-        public MyOnTuneListener() { }
-
         private void onTune(Channel channel, boolean wasUnderShrukenTvView) {
-            mStreamInfoUpdateTimeThresholdMs =
-                    System.currentTimeMillis() + FIRST_STREAM_INFO_UPDATE_DELAY_MILLIS;
+            Debug.getTimer(Debug.TAG_START_UP_TIMER).log("MainActivity.MyOnTuneListener.onTune");
             mChannel = channel;
             mWasUnderShrunkenTvView = wasUnderShrukenTvView;
         }
@@ -3249,7 +2594,8 @@
             if (mTvView.isFadedOut()) {
                 mTvView.removeFadeEffect();
             }
-            // TODO: show something to user about this error.
+            Toast.makeText(MainActivity.this, R.string.msg_channel_unavailable_unknown,
+                    Toast.LENGTH_SHORT).show();
         }
 
         @Override
@@ -3258,29 +2604,21 @@
                 mTracker.sendChannelTuneTime(info.getCurrentChannel(),
                         mTuneDurationTimer.reset());
             }
-            // If updateChannelBanner() is called without delay, the stream info seems flickering
-            // when the channel is quickly changed.
-            if (!mHandler.hasMessages(MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE)
-                    && info.isVideoAvailable()) {
-                if (System.currentTimeMillis() > mStreamInfoUpdateTimeThresholdMs) {
-                    updateChannelBannerAndShowIfNeeded(
-                            UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO);
-                } else {
-                    mHandler.sendMessageDelayed(mHandler.obtainMessage(
-                            MSG_UPDATE_CHANNEL_BANNER_BY_INFO_UPDATE),
-                            mStreamInfoUpdateTimeThresholdMs - System.currentTimeMillis());
-                }
+            if (info.isVideoOrAudioAvailable() && mChannel == getCurrentChannel()) {
+                mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                        TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_UPDATE_STREAM_INFO);
             }
-
             applyDisplayRefreshRate(info.getVideoFrameRate());
-            mTvViewUiManager.updateTvView();
+            mTvViewUiManager.updateTvAspectRatio();
             applyMultiAudio();
             applyClosedCaption();
-            // TODO: Send command to TIS with checking the settings in TV and CaptionManager.
             mOverlayManager.getMenu().onStreamInfoChanged();
             if (mTvView.isVideoAvailable()) {
                 mTvViewUiManager.fadeInTvView();
             }
+            if (!mTvView.isContentBlocked() && !mTvView.isScreenBlocked()) {
+                updateAvailabilityToast();
+            }
             mHandler.removeCallbacks(mRestoreMainViewRunnable);
             restoreMainTvView();
         }
@@ -3303,11 +2641,15 @@
             }
             mChannelTuner.setCurrentChannel(currentChannel);
             mTvView.setCurrentChannel(currentChannel);
-            updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_TUNE);
+            mOverlayManager.updateChannelBannerAndShowIfNeeded(
+                    TvOverlayManager.UPDATE_CHANNEL_BANNER_REASON_TUNE);
         }
 
         @Override
         public void onContentBlocked() {
+            Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+                    "MainActivity.MyOnTuneListener.onContentBlocked removes timer");
+            Debug.removeTimer(Debug.TAG_START_UP_TIMER);
             mTuneDurationTimer.reset();
             TvContentRating rating = mTvView.getBlockedContentRating();
             // When tuneTo was called while TV view was shrunken, if the channel id is the same
@@ -3319,9 +2661,9 @@
                 mUnlockAllowedRatingBeforeShrunken = isUnderShrunkenTvView();
                 mTvView.unblockContent(rating);
             }
-            mChannelBannerView.setBlockingContentRating(rating);
-            updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
+            mOverlayManager.setBlockingContentRating(rating);
             mTvViewUiManager.fadeInTvView();
+            mMediaSessionWrapper.update(true, getCurrentChannel(), getCurrentProgram());
         }
 
         @Override
@@ -3329,8 +2671,8 @@
             if (!isUnderShrunkenTvView()) {
                 mUnlockAllowedRatingBeforeShrunken = false;
             }
-            mChannelBannerView.setBlockingContentRating(null);
-            updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
+            mOverlayManager.setBlockingContentRating(null);
+            mMediaSessionWrapper.update(false, getCurrentChannel(), getCurrentProgram());
         }
     }
 }
diff --git a/src/com/android/tv/MainActivityWrapper.java b/src/com/android/tv/MainActivityWrapper.java
index 0173325..5af5079 100644
--- a/src/com/android/tv/MainActivityWrapper.java
+++ b/src/com/android/tv/MainActivityWrapper.java
@@ -61,7 +61,7 @@
      * Unsets the main activity instance.
      */
     public void onMainActivityDestroyed(@NonNull MainActivity activity) {
-        if (mActivity != activity) {
+        if (mActivity == activity) {
             mActivity = null;
         }
     }
diff --git a/src/com/android/tv/MediaSessionWrapper.java b/src/com/android/tv/MediaSessionWrapper.java
new file mode 100644
index 0000000..da6ad2a
--- /dev/null
+++ b/src/com/android/tv/MediaSessionWrapper.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2017 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;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.media.MediaMetadata;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
+import android.media.tv.TvContract;
+import android.media.tv.TvInputInfo;
+import android.os.AsyncTask;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+
+import com.android.tv.data.Channel;
+import com.android.tv.data.Program;
+import com.android.tv.util.ImageLoader;
+import com.android.tv.util.Utils;
+
+/**
+ * A wrapper class for {@link MediaSession} to support common operations on media sessions for
+ * {@link MainActivity}.
+ */
+class MediaSessionWrapper {
+    private static final String MEDIA_SESSION_TAG = "com.android.tv.mediasession";
+    private static PlaybackState MEDIA_SESSION_STATE_PLAYING = new PlaybackState.Builder()
+            .setState(PlaybackState.STATE_PLAYING, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 1.0f)
+            .build();
+    private static PlaybackState MEDIA_SESSION_STATE_STOPPED = new PlaybackState.Builder()
+            .setState(PlaybackState.STATE_STOPPED, PlaybackState.PLAYBACK_POSITION_UNKNOWN, 0.0f)
+            .build();
+
+    private final Context mContext;
+    private final MediaSession mMediaSession;
+    private int mNowPlayingCardWidth;
+    private int mNowPlayingCardHeight;
+
+    MediaSessionWrapper(Context context) {
+        mContext = context;
+        mMediaSession = new MediaSession(context, MEDIA_SESSION_TAG);
+        mMediaSession.setCallback(new MediaSession.Callback() {
+            @Override
+            public boolean onMediaButtonEvent(@NonNull Intent mediaButtonIntent) {
+                // Consume the media button event here. Should not send it to other apps.
+                return true;
+            }
+        });
+        mMediaSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS |
+                MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
+        mNowPlayingCardWidth = mContext.getResources().getDimensionPixelSize(
+                R.dimen.notif_card_img_max_width);
+        mNowPlayingCardHeight = mContext.getResources().getDimensionPixelSize(
+                R.dimen.notif_card_img_height);
+    }
+
+    /**
+     * Sets playback state.
+     *
+     * @param isPlaying {@code true} if TV is playing, otherwise {@code false}.
+     */
+    void setPlaybackState(boolean isPlaying) {
+        if (isPlaying) {
+            mMediaSession.setActive(true);
+            // setPlaybackState() has to be called after calling setActive(). b/31933276
+            mMediaSession.setPlaybackState(MEDIA_SESSION_STATE_PLAYING);
+        } else if (mMediaSession.isActive()) {
+            mMediaSession.setPlaybackState(MEDIA_SESSION_STATE_STOPPED);
+            mMediaSession.setActive(false);
+        }
+    }
+
+    /**
+     * Updates media session according to the current TV playback status.
+     *
+     * @param blocked {@code true} if the current channel is blocked, either by user settings or
+     *                the current program's content ratings.
+     * @param currentChannel The currently playing channel.
+     * @param currentProgram The currently playing program.
+     */
+    void update(boolean blocked, Channel currentChannel, Program currentProgram) {
+        if (currentChannel == null) {
+            setPlaybackState(false);
+            return;
+        }
+
+        // If the channel is blocked, display a lock and a short text on the Now Playing Card
+        if (blocked) {
+            Bitmap art = BitmapFactory.decodeResource(mContext.getResources(),
+                    R.drawable.ic_message_lock_preview);
+            updateMediaMetadata(mContext.getResources()
+                    .getString(R.string.channel_banner_locked_channel_title), art);
+            setPlaybackState(true);
+            return;
+        }
+
+        String cardTitleText = null;
+        String posterArtUri = null;
+        if (currentProgram != null) {
+            cardTitleText = currentProgram.getTitle();
+            posterArtUri = currentProgram.getPosterArtUri();
+        }
+        if (TextUtils.isEmpty(cardTitleText)) {
+            cardTitleText = getChannelName(currentChannel);
+        }
+        updateMediaMetadata(cardTitleText, null);
+        if (posterArtUri == null) {
+            posterArtUri = TvContract.buildChannelLogoUri(currentChannel.getId()).toString();
+        }
+        updatePosterArt(currentChannel, currentProgram, cardTitleText, null, posterArtUri);
+        setPlaybackState(true);
+    }
+
+    /**
+     * Releases the media session.
+     *
+     * @see MediaSession#release()
+     */
+    void release() {
+        mMediaSession.release();
+    }
+
+    private String getChannelName(Channel channel) {
+        if (channel.isPassthrough()) {
+            TvInputInfo input = TvApplication.getSingletons(mContext).getTvInputManagerHelper()
+                    .getTvInputInfo(channel.getInputId());
+            return Utils.loadLabel(mContext, input);
+        } else {
+            return channel.getDisplayName();
+        }
+    }
+
+    private void updatePosterArt(Channel currentChannel, Program currentProgram,
+            String cardTitleText, @Nullable Bitmap posterArt, @Nullable String posterArtUri) {
+        if (posterArt != null) {
+            updateMediaMetadata(cardTitleText, posterArt);
+        } else if (posterArtUri != null) {
+            ImageLoader.loadBitmap(mContext, posterArtUri, mNowPlayingCardWidth,
+                    mNowPlayingCardHeight, new ProgramPosterArtCallback(this, currentChannel,
+                            currentProgram, cardTitleText));
+        } else {
+            updateMediaMetadata(cardTitleText, R.drawable.default_now_card);
+        }
+    }
+
+    private void updateMediaMetadata(final String title, final Bitmap posterArt) {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... arg0) {
+                MediaMetadata.Builder builder = new MediaMetadata.Builder();
+                builder.putString(MediaMetadata.METADATA_KEY_TITLE, title);
+                if (posterArt != null) {
+                    builder.putBitmap(MediaMetadata.METADATA_KEY_ART, posterArt);
+                }
+                mMediaSession.setMetadata(builder.build());
+                return null;
+            }
+        }.execute();
+    }
+
+    private void updateMediaMetadata(final String title, final int imageResId) {
+        new AsyncTask<Void, Void, Void> () {
+            @Override
+            protected Void doInBackground(Void... arg0) {
+                MediaMetadata.Builder builder = new MediaMetadata.Builder();
+                builder.putString(MediaMetadata.METADATA_KEY_TITLE, title);
+                Bitmap posterArt =
+                        BitmapFactory.decodeResource(mContext.getResources(), imageResId);
+                if (posterArt != null) {
+                    builder.putBitmap(MediaMetadata.METADATA_KEY_ART, posterArt);
+                }
+                mMediaSession.setMetadata(builder.build());
+                return null;
+            }
+        }.execute();
+    }
+
+    private static class ProgramPosterArtCallback extends
+            ImageLoader.ImageLoaderCallback<MediaSessionWrapper> {
+        private final Channel mChannel;
+        private final Program mProgram;
+        private final String mCardTitleText;
+
+        ProgramPosterArtCallback(MediaSessionWrapper sessionWrapper, Channel channel,
+                Program program, String cardTitleText) {
+            super(sessionWrapper);
+            mChannel = channel;
+            mProgram = program;
+            mCardTitleText = cardTitleText;
+        }
+
+        @Override
+        public void onBitmapLoaded(MediaSessionWrapper sessionWrapper, @Nullable Bitmap posterArt) {
+            if (((MainActivity) sessionWrapper.mContext).isNowPlayingProgram(mChannel, mProgram)) {
+                sessionWrapper.updatePosterArt(mChannel, mProgram, mCardTitleText, posterArt, null);
+            }
+        }
+    }
+}
diff --git a/src/com/android/tv/SetupPassthroughActivity.java b/src/com/android/tv/SetupPassthroughActivity.java
index 8a263a2..f0f5441 100644
--- a/src/com/android/tv/SetupPassthroughActivity.java
+++ b/src/com/android/tv/SetupPassthroughActivity.java
@@ -18,19 +18,27 @@
 
 import android.app.Activity;
 import android.content.ActivityNotFoundException;
+import android.content.Context;
 import android.content.Intent;
 import android.media.tv.TvInputInfo;
 import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.annotation.MainThread;
 import android.util.Log;
 
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.TvCommonConstants;
+import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.ChannelDataManager.Listener;
 import com.android.tv.data.epg.EpgFetcher;
 import com.android.tv.experiments.Experiments;
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * An activity to launch a TV input setup activity.
  *
@@ -42,66 +50,83 @@
 
     private static final int REQUEST_START_SETUP_ACTIVITY = 200;
 
+    private static ScanTimeoutMonitor sScanTimeoutMonitor;
+
     private TvInputInfo mTvInputInfo;
     private Intent mActivityAfterCompletion;
+    private boolean mEpgFetcherDuringScan;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        if (DEBUG) Log.d(TAG, "onCreate");
         super.onCreate(savedInstanceState);
-        Intent intent = getIntent();
-        SoftPreconditions.checkState(
-                intent.getAction().equals(TvCommonConstants.INTENT_ACTION_INPUT_SETUP));
         ApplicationSingletons appSingletons = TvApplication.getSingletons(this);
         TvInputManagerHelper inputManager = appSingletons.getTvInputManagerHelper();
+        Intent intent = getIntent();
         String inputId = intent.getStringExtra(TvCommonConstants.EXTRA_INPUT_ID);
         mTvInputInfo = inputManager.getTvInputInfo(inputId);
-        if (DEBUG) Log.d(TAG, "TvInputId " + inputId + " / TvInputInfo " + mTvInputInfo);
-        if (mTvInputInfo == null) {
-            Log.w(TAG, "There is no input with the ID " + inputId + ".");
-            finish();
-            return;
-        }
-        Intent setupIntent = intent.getExtras().getParcelable(TvCommonConstants.EXTRA_SETUP_INTENT);
-        if (DEBUG) Log.d(TAG, "Setup activity launch intent: " + setupIntent);
-        if (setupIntent == null) {
-            Log.w(TAG, "The input (" + mTvInputInfo.getId() + ") doesn't have setup.");
-            finish();
-            return;
-        }
-        SetupUtils.grantEpgPermission(this, mTvInputInfo.getServiceInfo().packageName);
         mActivityAfterCompletion = intent.getParcelableExtra(
                 TvCommonConstants.EXTRA_ACTIVITY_AFTER_COMPLETION);
-        if (DEBUG) Log.d(TAG, "Activity after completion " + mActivityAfterCompletion);
-        // If EXTRA_SETUP_INTENT is not removed, an infinite recursion happens during
-        // setupIntent.putExtras(intent.getExtras()).
-        Bundle extras = intent.getExtras();
-        extras.remove(TvCommonConstants.EXTRA_SETUP_INTENT);
-        setupIntent.putExtras(extras);
-        try {
-            startActivityForResult(setupIntent, REQUEST_START_SETUP_ACTIVITY);
-        } catch (ActivityNotFoundException e) {
-            Log.e(TAG, "Can't find activity: " + setupIntent.getComponent());
-            finish();
-            return;
+        boolean needToFetchEpg = Utils.isInternalTvInput(this, mTvInputInfo.getId())
+                && Experiments.CLOUD_EPG.get();
+        if (needToFetchEpg) {
+            // In case when the activity is restored, this flag should be restored as well.
+            mEpgFetcherDuringScan = true;
         }
-        if (Utils.isInternalTvInput(this, mTvInputInfo.getId()) && Experiments.CLOUD_EPG.get()) {
-            EpgFetcher.getInstance(this).stop();
+        if (savedInstanceState == null) {
+            SoftPreconditions.checkState(
+                    intent.getAction().equals(TvCommonConstants.INTENT_ACTION_INPUT_SETUP));
+            if (DEBUG) Log.d(TAG, "TvInputId " + inputId + " / TvInputInfo " + mTvInputInfo);
+            if (mTvInputInfo == null) {
+                Log.w(TAG, "There is no input with the ID " + inputId + ".");
+                finish();
+                return;
+            }
+            Intent setupIntent =
+                    intent.getExtras().getParcelable(TvCommonConstants.EXTRA_SETUP_INTENT);
+            if (DEBUG) Log.d(TAG, "Setup activity launch intent: " + setupIntent);
+            if (setupIntent == null) {
+                Log.w(TAG, "The input (" + mTvInputInfo.getId() + ") doesn't have setup.");
+                finish();
+                return;
+            }
+            SetupUtils.grantEpgPermission(this, mTvInputInfo.getServiceInfo().packageName);
+            if (DEBUG) Log.d(TAG, "Activity after completion " + mActivityAfterCompletion);
+            // If EXTRA_SETUP_INTENT is not removed, an infinite recursion happens during
+            // setupIntent.putExtras(intent.getExtras()).
+            Bundle extras = intent.getExtras();
+            extras.remove(TvCommonConstants.EXTRA_SETUP_INTENT);
+            setupIntent.putExtras(extras);
+            try {
+                startActivityForResult(setupIntent, REQUEST_START_SETUP_ACTIVITY);
+            } catch (ActivityNotFoundException e) {
+                Log.e(TAG, "Can't find activity: " + setupIntent.getComponent());
+                finish();
+                return;
+            }
+            if (needToFetchEpg) {
+                if (sScanTimeoutMonitor == null) {
+                    sScanTimeoutMonitor = new ScanTimeoutMonitor(this);
+                }
+                sScanTimeoutMonitor.startMonitoring();
+                EpgFetcher.getInstance(this).onChannelScanStarted();
+            }
         }
     }
 
     @Override
-    protected void onDestroy() {
-        if (mTvInputInfo != null && Utils.isInternalTvInput(this, mTvInputInfo.getId())
-                && Experiments.CLOUD_EPG.get()) {
-            EpgFetcher.getInstance(this).start();
-        }
-        super.onDestroy();
-    }
-
-    @Override
     public void onActivityResult(int requestCode, final int resultCode, final Intent data) {
+        if (DEBUG) Log.d(TAG, "onActivityResult");
+        if (sScanTimeoutMonitor != null) {
+            sScanTimeoutMonitor.stopMonitoring();
+        }
+        // Note: It's not guaranteed that this method is always called after scanning.
         boolean setupComplete = requestCode == REQUEST_START_SETUP_ACTIVITY
                 && resultCode == Activity.RESULT_OK;
+        // Tells EpgFetcher that channel source setup is finished.
+        if (mEpgFetcherDuringScan) {
+            EpgFetcher.getInstance(this).onChannelScanFinished();
+        }
         if (!setupComplete) {
             setResult(resultCode, data);
             finish();
@@ -122,4 +147,75 @@
             }
         });
     }
+
+    /**
+     * Monitors the scan progress and notifies the timeout of the scanning.
+     * The purpose of this monitor is to call EpgFetcher.onChannelScanFinished() in case when
+     * SetupPassthroughActivity.onActivityResult() is not called properly. b/36008534
+     */
+    @MainThread
+    private static class ScanTimeoutMonitor {
+        // Set timeout long enough. The message in Sony TV says the scanning takes about 30 minutes.
+        private static final long SCAN_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(30);
+
+        private final Context mContext;
+        private final ChannelDataManager mChannelDataManager;
+        private final Handler mHandler = new Handler(Looper.getMainLooper());
+        private final Runnable mScanTimeoutRunnable = new Runnable() {
+            @Override
+            public void run() {
+                Log.w(TAG, "No channels has been added for a while." +
+                        " The scan might have finished unexpectedly.");
+                onScanTimedOut();
+            }
+        };
+        private final Listener mChannelDataManagerListener = new Listener() {
+            @Override
+            public void onLoadFinished() {
+                setupTimer();
+            }
+
+            @Override
+            public void onChannelListUpdated() {
+                setupTimer();
+            }
+
+            @Override
+            public void onChannelBrowsableChanged() { }
+        };
+        private boolean mStarted;
+
+        private ScanTimeoutMonitor(Context context) {
+            mContext = context.getApplicationContext();
+            mChannelDataManager = TvApplication.getSingletons(context).getChannelDataManager();
+        }
+
+        private void startMonitoring() {
+            if (!mStarted) {
+                mStarted = true;
+                mChannelDataManager.addListener(mChannelDataManagerListener);
+            }
+            if (mChannelDataManager.isDbLoadFinished()) {
+                setupTimer();
+            }
+        }
+
+        private void stopMonitoring() {
+            if (mStarted) {
+                mStarted = false;
+                mHandler.removeCallbacks(mScanTimeoutRunnable);
+                mChannelDataManager.removeListener(mChannelDataManagerListener);
+            }
+        }
+
+        private void setupTimer() {
+            mHandler.removeCallbacks(mScanTimeoutRunnable);
+            mHandler.postDelayed(mScanTimeoutRunnable, SCAN_TIMEOUT_MS);
+        }
+
+        private void onScanTimedOut() {
+            stopMonitoring();
+            EpgFetcher.getInstance(mContext).onChannelScanFinished();
+        }
+    }
 }
diff --git a/src/com/android/tv/TimeShiftManager.java b/src/com/android/tv/TimeShiftManager.java
index 2d6d45c..7088593 100644
--- a/src/com/android/tv/TimeShiftManager.java
+++ b/src/com/android/tv/TimeShiftManager.java
@@ -161,7 +161,6 @@
     @TimeShiftActionId
     private int mLastActionId = 0;
 
-    // TODO: Remove these variables once API level 23 is available.
     private final Context mContext;
 
     private Program mCurrentProgram;
@@ -618,6 +617,15 @@
                                 + mAvailablityChangedTimeMs);
                         return;
                     }
+                    if (recordStartTimeMs > System.currentTimeMillis()) {
+                        // The time reported by TvInputService might not consistent with system
+                        // clock,, use system's current time instead.
+                        Log.e(TAG, "The start time should not be earlier than the current time, "
+                                + "reset the start time to the system's current time: {"
+                                + "startTime: " + recordStartTimeMs + ", current time: "
+                                + System.currentTimeMillis());
+                        recordStartTimeMs = System.currentTimeMillis();
+                    }
                     if (mRecordStartTimeMs == recordStartTimeMs) {
                         return;
                     }
@@ -887,10 +895,12 @@
             }
 
             long fetchStartTimeMs = Utils.floorTime(startTimeMs, MAX_DUMMY_PROGRAM_DURATION);
-            boolean needToLoad = addDummyPrograms(fetchStartTimeMs,
-                    endTimeMs + PREFETCH_DURATION_FOR_NEXT);
+            long fetchEndTimeMs = Utils.ceilTime(endTimeMs + PREFETCH_DURATION_FOR_NEXT,
+                    MAX_DUMMY_PROGRAM_DURATION);
+            removeOutdatedPrograms(fetchStartTimeMs);
+            boolean needToLoad = addDummyPrograms(fetchStartTimeMs, fetchEndTimeMs);
             if (needToLoad) {
-                Range<Long> period = Range.create(fetchStartTimeMs, endTimeMs);
+                Range<Long> period = Range.create(fetchStartTimeMs, fetchEndTimeMs);
                 mProgramLoadQueue.add(period);
                 startTaskIfNeeded();
             }
@@ -996,6 +1006,12 @@
             return added;
         }
 
+        private void removeOutdatedPrograms(long startTimeMs) {
+            while (mPrograms.size() > 0 && mPrograms.get(0).getEndTimeUtcMillis() <= startTimeMs) {
+                mPrograms.remove(0);
+            }
+        }
+
         private void removeDummyPrograms() {
             for (Iterator<Program> it = mPrograms.listIterator(); it.hasNext(); ) {
                 if (!it.next().isValid()) {
@@ -1012,7 +1028,7 @@
             for (int i = 0, j = 0; i < mPrograms.size() && j < loadedPrograms.size(); ++j) {
                 Program loadedProgram = loadedPrograms.get(j);
                 // Skip previous programs.
-                while (program.getEndTimeUtcMillis() < loadedProgram.getStartTimeUtcMillis()) {
+                while (program.getEndTimeUtcMillis() <= loadedProgram.getStartTimeUtcMillis()) {
                     // Reached end of mPrograms.
                     if (++i == mPrograms.size()) {
                         return;
diff --git a/src/com/android/tv/TvApplication.java b/src/com/android/tv/TvApplication.java
index 0e18a25..0c7c0fd 100644
--- a/src/com/android/tv/TvApplication.java
+++ b/src/com/android/tv/TvApplication.java
@@ -22,16 +22,20 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.media.tv.TvContract;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
 import android.media.tv.TvInputManager.TvInputCallback;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.StrictMode;
 import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -49,19 +53,30 @@
 import com.android.tv.config.DefaultConfigManager;
 import com.android.tv.config.RemoteConfig;
 import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.PreviewDataManager;
 import com.android.tv.data.ProgramDataManager;
+import com.android.tv.data.epg.EpgFetcher;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManagerImpl;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrRecordingService;
 import com.android.tv.dvr.DvrScheduleManager;
 import com.android.tv.dvr.DvrStorageStatusManager;
 import com.android.tv.dvr.DvrWatchedPositionManager;
+import com.android.tv.dvr.recorder.RecordingScheduler;
+import com.android.tv.perf.EventNames;
+import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.perf.StubPerformanceMonitor;
+import com.android.tv.perf.TimerEvent;
+import com.android.tv.recommendation.ChannelPreviewUpdater;
+import com.android.tv.recommendation.RecordedProgramPreviewUpdater;
+import com.android.tv.tuner.TunerInputController;
 import com.android.tv.tuner.TunerPreferences;
 import com.android.tv.tuner.tvinput.TunerTvInputService;
 import com.android.tv.tuner.util.TunerInputInfoUtils;
 import com.android.tv.util.AccountHelper;
 import com.android.tv.util.Clock;
+import com.android.tv.util.Debug;
+import com.android.tv.util.PermissionUtils;
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.SystemProperties;
 import com.android.tv.util.TvInputManagerHelper;
@@ -72,17 +87,25 @@
 public class TvApplication extends Application implements ApplicationSingletons {
     private static final String TAG = "TvApplication";
     private static final boolean DEBUG = false;
-    private RemoteConfig mRemoteConfig;
+    private static final TimerEvent sAppStartTimer = StubPerformanceMonitor.startBootstrapTimer();
+
+    /**
+     * An instance of {@link ApplicationSingletons}. Note that this can be set directly only for the
+     * test purpose.
+     */
+    @VisibleForTesting
+    public static ApplicationSingletons sAppSingletons;
 
     /**
      * Broadcast Action: The user has updated LC to a new version that supports tuner input.
-     * {@link TunerInputController} will recevice this intent to check the existence of tuner
-     * input when the new version is first launched.
+     * {@link com.android.tv.tuner.TunerInputController} will recevice this intent to check
+     * the existence of tuner input when the new version is first launched.
      */
     public static final String ACTION_APPLICATION_FIRST_LAUNCHED =
             "com.android.tv.action.APPLICATION_FIRST_LAUNCHED";
     private static final String PREFERENCE_IS_FIRST_LAUNCH = "is_first_launch";
 
+    private RemoteConfig mRemoteConfig;
     private String mVersionName = "";
 
     private final MainActivityWrapper mMainActivityWrapper = new MainActivityWrapper();
@@ -92,21 +115,30 @@
     private Tracker mTracker;
     private TvInputManagerHelper mTvInputManagerHelper;
     private ChannelDataManager mChannelDataManager;
-    private ProgramDataManager mProgramDataManager;
+    private volatile ProgramDataManager mProgramDataManager;
+    private PreviewDataManager mPreviewDataManager;
     private DvrManager mDvrManager;
     private DvrScheduleManager mDvrScheduleManager;
     private DvrDataManager mDvrDataManager;
     private DvrStorageStatusManager mDvrStorageStatusManager;
     private DvrWatchedPositionManager mDvrWatchedPositionManager;
+    private RecordingScheduler mRecordingScheduler;
     @Nullable
     private InputSessionManager mInputSessionManager;
     private AccountHelper mAccountHelper;
     // When this variable is null, we don't know in which process TvApplication runs.
     private Boolean mRunningInMainProcess;
+    private PerformanceMonitor mPerformanceMonitor;
 
     @Override
     public void onCreate() {
         super.onCreate();
+        if (!PermissionUtils.hasInternet(this)) {
+            // When an isolated process starts, just skip all the initialization.
+            return;
+        }
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).start();
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("Start TvApplication.onCreate");
         SharedPreferencesUtils.initialize(this, new Runnable() {
             @Override
             public void run() {
@@ -127,18 +159,15 @@
         }
         Log.i(TAG, "Starting Live TV " + getVersionName());
 
-
         // Only set StrictMode for ENG builds because the build server only produces userdebug
         // builds.
         if (BuildConfig.ENG && SystemProperties.ALLOW_STRICT_MODE.getValue()) {
             StrictMode.ThreadPolicy.Builder threadPolicyBuilder =
                     new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog();
             StrictMode.VmPolicy.Builder vmPolicyBuilder =
-                    new StrictMode.VmPolicy.Builder().detectAll().penaltyLog();
+                    new StrictMode.VmPolicy.Builder().detectAll().penaltyDeath();
             if (!TvCommonUtils.isRunningInTest()) {
                 threadPolicyBuilder.penaltyDialog();
-                // Turn off death penalty for tests b/23355898
-                vmPolicyBuilder.penaltyDeath();
             }
             StrictMode.setThreadPolicy(threadPolicyBuilder.build());
             StrictMode.setVmPolicy(vmPolicyBuilder.build());
@@ -149,13 +178,16 @@
             mAnalytics = StubAnalytics.getInstance(this);
         }
         mTracker = mAnalytics.getDefaultTracker();
-        mTvInputManagerHelper = new TvInputManagerHelper(this);
-        mTvInputManagerHelper.start();
+        getTvInputManagerHelper();
         // In SetupFragment, transitions are set in the constructor. Because the fragment can be
         // created in Activity.onCreate() by the framework, SetupAnimationHelper should be
         // initialized here before Activity.onCreate() is called.
         SetupAnimationHelper.initialize(this);
+
+
         Log.i(TAG, "Started Live TV " + mVersionName);
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("finish TvApplication.onCreate");
+        getPerformanceMonitor().stopTimer(sAppStartTimer, EventNames.APPLICATION_ONCREATE);
     }
 
     private void setCurrentRunningProcess(boolean isMainProcess) {
@@ -163,12 +195,22 @@
             SoftPreconditions.checkState(isMainProcess == mRunningInMainProcess);
             return;
         }
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+                "start TvApplication.setCurrentRunningProcess");
         mRunningInMainProcess = isMainProcess;
         if (CommonFeatures.DVR.isEnabled(this)) {
             mDvrStorageStatusManager = new DvrStorageStatusManager(this, mRunningInMainProcess);
         }
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                // Fetch remote config
+                getRemoteConfig().fetch(null);
+                return null;
+            }
+        }.execute();
         if (mRunningInMainProcess) {
-            mTvInputManagerHelper.addCallback(new TvInputCallback() {
+            getTvInputManagerHelper().addCallback(new TvInputCallback() {
                 @Override
                 public void onInputAdded(String inputId) {
                     if (Features.TUNER.isEnabled(TvApplication.this) && TextUtils.equals(inputId,
@@ -186,15 +228,22 @@
             if (Features.TUNER.isEnabled(this)) {
                 // If the tuner input service is added before the app is started, we need to
                 // handle it here.
-                TunerInputInfoUtils.updateTunerInputInfo(this);
+                TunerInputInfoUtils.updateTunerInputInfo(TvApplication.this);
             }
             if (CommonFeatures.DVR.isEnabled(this)) {
                 mDvrScheduleManager = new DvrScheduleManager(this);
                 mDvrManager = new DvrManager(this);
-                //NOTE: DvrRecordingService just keeps running.
-                DvrRecordingService.startService(this);
+                mRecordingScheduler = RecordingScheduler.createScheduler(this);
+            }
+            EpgFetcher.getInstance(this).startRoutineService();
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                ChannelPreviewUpdater.getInstance(this).startRoutineService();
+                RecordedProgramPreviewUpdater.getInstance(this)
+                        .updatePreviewDataForRecordedPrograms();
             }
         }
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+                "finish TvApplication.setCurrentRunningProcess");
     }
 
     private void checkTunerServiceOnFirstLaunch() {
@@ -203,7 +252,7 @@
         boolean isFirstLaunch = sharedPreferences.getBoolean(PREFERENCE_IS_FIRST_LAUNCH, true);
         if (isFirstLaunch) {
             if (DEBUG) Log.d(TAG, "Congratulations, it's the first launch!");
-            sendBroadcast(new Intent(ACTION_APPLICATION_FIRST_LAUNCHED));
+            TunerInputController.onCheckingUsbTunerStatus(this, ACTION_APPLICATION_FIRST_LAUNCHED);
             SharedPreferences.Editor editor = sharedPreferences.edit();
             editor.putBoolean(PREFERENCE_IS_FIRST_LAUNCH, false);
             editor.apply();
@@ -227,6 +276,15 @@
     }
 
     /**
+     * Returns the {@link RecordingScheduler}.
+     */
+    @Override
+    @Nullable
+    public RecordingScheduler getRecordingScheduler() {
+        return mRecordingScheduler;
+    }
+
+    /**
      * Returns the {@link DvrWatchedPositionManager}.
      */
     @Override
@@ -268,24 +326,55 @@
     @Override
     public ChannelDataManager getChannelDataManager() {
         if (mChannelDataManager == null) {
-            mChannelDataManager = new ChannelDataManager(this, mTvInputManagerHelper);
+            mChannelDataManager = new ChannelDataManager(this, getTvInputManagerHelper());
             mChannelDataManager.start();
         }
         return mChannelDataManager;
     }
 
+    @Override
+    public boolean isChannelDataManagerLoadFinished() {
+        return mChannelDataManager != null && mChannelDataManager.isDbLoadFinished();
+    }
+
     /**
      * Returns {@link ProgramDataManager}.
      */
     @Override
     public ProgramDataManager getProgramDataManager() {
-        if (mProgramDataManager == null) {
-            mProgramDataManager = new ProgramDataManager(this);
-            mProgramDataManager.start();
+        if (mProgramDataManager != null) {
+            return mProgramDataManager;
         }
+        Utils.runInMainThreadAndWait(new Runnable() {
+            @Override
+            public void run() {
+                if (mProgramDataManager == null) {
+                    mProgramDataManager = new ProgramDataManager(TvApplication.this);
+                    mProgramDataManager.start();
+                }
+            }
+        });
         return mProgramDataManager;
     }
 
+    @Override
+    public boolean isProgramDataManagerCurrentProgramsLoadFinished() {
+        return mProgramDataManager != null && mProgramDataManager.isCurrentProgramsLoadFinished();
+    }
+
+    /**
+     * Returns {@link PreviewDataManager}.
+     */
+    @TargetApi(Build.VERSION_CODES.O)
+    @Override
+    public PreviewDataManager getPreviewDataManager() {
+        if (mPreviewDataManager == null) {
+            mPreviewDataManager = new PreviewDataManager(this);
+            mPreviewDataManager.start();
+        }
+        return mPreviewDataManager;
+    }
+
     /**
      * Returns {@link DvrDataManager}.
      */
@@ -314,6 +403,10 @@
      */
     @Override
     public TvInputManagerHelper getTvInputManagerHelper() {
+        if (mTvInputManagerHelper == null) {
+            mTvInputManagerHelper = new TvInputManagerHelper(this);
+            mTvInputManagerHelper.start();
+        }
         return mTvInputManagerHelper;
     }
 
@@ -345,6 +438,19 @@
         return mRemoteConfig;
     }
 
+    @Override
+    public boolean isRunningInMainProcess() {
+        return mRunningInMainProcess != null && mRunningInMainProcess;
+    }
+
+    @Override
+    public PerformanceMonitor getPerformanceMonitor() {
+        if (mPerformanceMonitor == null) {
+            mPerformanceMonitor = StubPerformanceMonitor.initialize(this);
+        }
+        return mPerformanceMonitor;
+    }
+
     /**
      * SelectInputActivity is set in {@link SelectInputActivity#onCreate} and cleared in
      * {@link SelectInputActivity#onDestroy}.
@@ -353,6 +459,14 @@
         mSelectInputActivity = activity;
     }
 
+    public void handleGuideKey() {
+        if (!mMainActivityWrapper.isResumed()) {
+            startActivity(new Intent(Intent.ACTION_VIEW, TvContract.Programs.CONTENT_URI));
+        } else {
+            mMainActivityWrapper.getMainActivity().getOverlayManager().toggleProgramGuide();
+        }
+    }
+
     /**
      * Handles the global key KEYCODE_TV.
      */
@@ -471,6 +585,7 @@
         if (packageManager.getComponentEnabledSetting(name) != newState) {
             packageManager.setComponentEnabledSetting(name, newState,
                     dontKillApp ? PackageManager.DONT_KILL_APP : 0);
+            Log.i(TAG, (enable ? "Un-hide" : "Hide") + " Live TV.");
         }
         SetupUtils.getInstance(TvApplication.this).onInputListUpdated(inputManager);
     }
@@ -479,7 +594,11 @@
      * Returns the @{@link ApplicationSingletons} using the application context.
      */
     public static ApplicationSingletons getSingletons(Context context) {
-        return (ApplicationSingletons) context.getApplicationContext();
+        // No need to be "synchronized" because this doesn't create any instance.
+        if (sAppSingletons == null) {
+            sAppSingletons = (ApplicationSingletons) context.getApplicationContext();
+        }
+        return sAppSingletons;
     }
 
     /**
@@ -491,6 +610,7 @@
      * specific initializations.
      */
     public static void setCurrentRunningProcess(Context context, boolean isMainProcess) {
+        // TODO(b/63064354) TvApplication should not have to know if it is "the main process"
         if (context.getApplicationContext() instanceof TvApplication) {
             TvApplication tvApplication = (TvApplication) context.getApplicationContext();
             tvApplication.setCurrentRunningProcess(isMainProcess);
diff --git a/src/com/android/tv/TvOptionsManager.java b/src/com/android/tv/TvOptionsManager.java
index 7871cbe..493e039 100644
--- a/src/com/android/tv/TvOptionsManager.java
+++ b/src/com/android/tv/TvOptionsManager.java
@@ -18,14 +18,13 @@
 
 import android.content.Context;
 import android.media.tv.TvTrackInfo;
+import android.support.annotation.IntDef;
 import android.util.SparseArray;
 
 import com.android.tv.data.DisplayMode;
-import com.android.tv.util.TvSettings;
-import com.android.tv.util.TvSettings.PipLayout;
-import com.android.tv.util.TvSettings.PipSize;
-import com.android.tv.util.TvSettings.PipSound;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Locale;
 
 /**
@@ -33,39 +32,34 @@
  * captions and display mode. Can be also used to create MenuAction items to control such options.
  */
 public class TvOptionsManager {
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({OPTION_CLOSED_CAPTIONS, OPTION_DISPLAY_MODE, OPTION_SYSTEMWIDE_PIP, OPTION_MULTI_AUDIO,
+            OPTION_MORE_CHANNELS, OPTION_DEVELOPER, OPTION_SETTINGS})
+    public @interface OptionType {}
     public static final int OPTION_CLOSED_CAPTIONS = 0;
     public static final int OPTION_DISPLAY_MODE = 1;
-    public static final int OPTION_IN_APP_PIP = 2;
-    public static final int OPTION_SYSTEMWIDE_PIP = 3;
-    public static final int OPTION_MULTI_AUDIO = 4;
-    public static final int OPTION_MORE_CHANNELS = 5;
-    public static final int OPTION_DEVELOPER = 6;
-    public static final int OPTION_SETTINGS = 7;
-
-    public static final int OPTION_PIP_INPUT = 100;
-    public static final int OPTION_PIP_SWAP = 101;
-    public static final int OPTION_PIP_SOUND = 102;
-    public static final int OPTION_PIP_LAYOUT = 103 ;
-    public static final int OPTION_PIP_SIZE = 104;
+    public static final int OPTION_SYSTEMWIDE_PIP = 2;
+    public static final int OPTION_MULTI_AUDIO = 3;
+    public static final int OPTION_MORE_CHANNELS = 4;
+    public static final int OPTION_DEVELOPER = 5;
+    public static final int OPTION_SETTINGS = 6;
 
     private final Context mContext;
     private final SparseArray<OptionChangedListener> mOptionChangedListeners = new SparseArray<>();
 
     private String mClosedCaptionsLanguage;
     private int mDisplayMode;
-    private boolean mPip;
     private String mMultiAudio;
-    private String mPipInput;
-    private boolean mPipSwap;
-    @PipSound private int mPipSound;
-    @PipLayout private int mPipLayout;
-    @PipSize private int mPipSize;
 
     public TvOptionsManager(Context context) {
         mContext = context;
     }
 
-    public String getOptionString(int option) {
+    /**
+     * Returns a suitable displayed string for the given option type under current settings.
+     * @param option the type of option, should be one of {@link OptionType}.
+     */
+    public String getOptionString(@OptionType int option) {
         switch (option) {
             case OPTION_CLOSED_CAPTIONS:
                 if (mClosedCaptionsLanguage == null) {
@@ -77,101 +71,48 @@
                         .isDisplayModeAvailable(mDisplayMode)
                         ? DisplayMode.getLabel(mDisplayMode, mContext)
                         : DisplayMode.getLabel(DisplayMode.MODE_NORMAL, mContext);
-            case OPTION_IN_APP_PIP:
-                return mContext.getString(
-                        mPip ? R.string.options_item_pip_on : R.string.options_item_pip_off);
             case OPTION_MULTI_AUDIO:
                 return mMultiAudio;
-            case OPTION_PIP_INPUT:
-                return mPipInput;
-            case OPTION_PIP_SWAP:
-                return mContext.getString(mPipSwap ? R.string.pip_options_item_swap_on
-                        : R.string.pip_options_item_swap_off);
-            case OPTION_PIP_SOUND:
-                if (mPipSound == TvSettings.PIP_SOUND_MAIN) {
-                    return mContext.getString(R.string.pip_options_item_sound_main);
-                } else if (mPipSound == TvSettings.PIP_SOUND_PIP_WINDOW) {
-                    return mContext.getString(R.string.pip_options_item_sound_pip_window);
-                }
-                break;
-            case OPTION_PIP_LAYOUT:
-                if (mPipLayout == TvSettings.PIP_LAYOUT_BOTTOM_RIGHT) {
-                    return mContext.getString(R.string.pip_options_item_layout_bottom_right);
-                } else if (mPipLayout == TvSettings.PIP_LAYOUT_TOP_RIGHT) {
-                    return mContext.getString(R.string.pip_options_item_layout_top_right);
-                } else if (mPipLayout == TvSettings.PIP_LAYOUT_TOP_LEFT) {
-                    return mContext.getString(R.string.pip_options_item_layout_top_left);
-                } else if (mPipLayout == TvSettings.PIP_LAYOUT_BOTTOM_LEFT) {
-                    return mContext.getString(R.string.pip_options_item_layout_bottom_left);
-                } else if (mPipLayout == TvSettings.PIP_LAYOUT_SIDE_BY_SIDE) {
-                    return mContext.getString(R.string.pip_options_item_layout_side_by_side);
-                }
-                break;
-            case OPTION_PIP_SIZE:
-                if (mPipSize == TvSettings.PIP_SIZE_BIG) {
-                    return mContext.getString(R.string.pip_options_item_size_big);
-                } else if (mPipSize == TvSettings.PIP_SIZE_SMALL) {
-                    return mContext.getString(R.string.pip_options_item_size_small);
-                }
-                break;
         }
         return "";
     }
 
-    public void onClosedCaptionsChanged(TvTrackInfo track) {
-        mClosedCaptionsLanguage = (track == null) ? null
-                : (track.getLanguage() != null) ? track.getLanguage()
-                        : mContext.getString(R.string.default_language);
+    /**
+     * Handles changing selection of closed caption.
+     */
+    public void onClosedCaptionsChanged(TvTrackInfo track, int trackIndex) {
+        mClosedCaptionsLanguage = (track == null) ?
+                null : (track.getLanguage() != null) ? track.getLanguage()
+                : mContext.getString(R.string.closed_caption_unknown_language, trackIndex + 1);
         notifyOptionChanged(OPTION_CLOSED_CAPTIONS);
     }
 
+    /**
+     * Handles changing selection of display mode.
+     */
     public void onDisplayModeChanged(int displayMode) {
         mDisplayMode = displayMode;
         notifyOptionChanged(OPTION_DISPLAY_MODE);
     }
 
-    public void onPipChanged(boolean pip) {
-        mPip = pip;
-        notifyOptionChanged(OPTION_IN_APP_PIP);
-    }
-
+    /**
+     * Handles changing selection of multi-audio.
+     */
     public void onMultiAudioChanged(String multiAudio) {
         mMultiAudio = multiAudio;
         notifyOptionChanged(OPTION_MULTI_AUDIO);
     }
 
-    public void onPipInputChanged(String pipInput) {
-        mPipInput = pipInput;
-        notifyOptionChanged(OPTION_PIP_INPUT);
-    }
-
-    public void onPipSwapChanged(boolean pipSwap) {
-        mPipSwap = pipSwap;
-        notifyOptionChanged(OPTION_PIP_SWAP);
-    }
-
-    public void onPipSoundChanged(@PipSound int pipSound) {
-        mPipSound = pipSound;
-        notifyOptionChanged(OPTION_PIP_SOUND);
-    }
-
-    public void onPipLayoutChanged(@PipLayout int pipLayout) {
-        mPipLayout = pipLayout;
-        notifyOptionChanged(OPTION_PIP_LAYOUT);
-    }
-
-    public void onPipSizeChanged(@PipSize int pipSize) {
-        mPipSize = pipSize;
-        notifyOptionChanged(OPTION_PIP_SIZE);
-    }
-
-    private void notifyOptionChanged(int option) {
+    private void notifyOptionChanged(@OptionType int option) {
         OptionChangedListener listener = mOptionChangedListeners.get(option);
         if (listener != null) {
-            listener.onOptionChanged(getOptionString(option));
+            listener.onOptionChanged(option, getOptionString(option));
         }
     }
 
+    /**
+     * Sets listeners to changes of the given option type.
+     */
     public void setOptionChangedListener(int option, OptionChangedListener listener) {
         mOptionChangedListeners.put(option, listener);
     }
@@ -180,6 +121,6 @@
      * An interface used to monitor option changes.
      */
     public interface OptionChangedListener {
-        void onOptionChanged(String newOption);
+        void onOptionChanged(@OptionType int optionType, String newString);
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/analytics/DurationTimer.java b/src/com/android/tv/analytics/DurationTimer.java
deleted file mode 100644
index ad2d91f..0000000
--- a/src/com/android/tv/analytics/DurationTimer.java
+++ /dev/null
@@ -1,62 +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.analytics;
-
-import android.os.SystemClock;
-
-/**
- * Times a duration.
- */
-public final class DurationTimer {
-    public static final long TIME_NOT_SET = -1;
-
-    private long startTimeMs = TIME_NOT_SET;
-
-    /**
-     * Returns true if the timer is running.
-     */
-    public boolean isRunning() {
-        return startTimeMs != TIME_NOT_SET;
-    }
-
-    /**
-     * Start the timer.
-     */
-    public void start() {
-        startTimeMs = SystemClock.elapsedRealtime();
-    }
-
-    /**
-     * Returns the current duration in milliseconds or {@link #TIME_NOT_SET} if the timer is not
-     * running.
-     */
-    public long getDuration() {
-        return isRunning() ? SystemClock.elapsedRealtime() - startTimeMs : TIME_NOT_SET;
-    }
-
-    /**
-     * Stops the timer and resets its value to {@link #TIME_NOT_SET}.
-     *
-     * @return the current duration in milliseconds or {@link #TIME_NOT_SET} if the timer is not
-     * running.
-     */
-    public long reset() {
-        long duration = getDuration();
-        startTimeMs = TIME_NOT_SET;
-        return duration;
-    }
-}
diff --git a/src/com/android/tv/config/DefaultConfigManager.java b/src/com/android/tv/config/DefaultConfigManager.java
index f5a6e95..bbabc6d 100644
--- a/src/com/android/tv/config/DefaultConfigManager.java
+++ b/src/com/android/tv/config/DefaultConfigManager.java
@@ -22,6 +22,7 @@
  * Stub Remote Config.
  */
 public class DefaultConfigManager {
+    public static final long DEFAULT_LONG_VALUE = 0;
     public static DefaultConfigManager createInstance(Context context) {
         return new DefaultConfigManager();
     }
@@ -47,6 +48,11 @@
         public boolean getBoolean(String key) {
             return false;
         }
+
+        @Override
+        public long getLong(String key) {
+            return DEFAULT_LONG_VALUE;
+        }
     }
 }
 
diff --git a/src/com/android/tv/config/RemoteConfig.java b/src/com/android/tv/config/RemoteConfig.java
index 0f7d2c5..f7ae87e 100644
--- a/src/com/android/tv/config/RemoteConfig.java
+++ b/src/com/android/tv/config/RemoteConfig.java
@@ -45,4 +45,7 @@
      * Gets value as a boolean corresponding to the specified key.
      */
     boolean getBoolean(String key);
+
+    /** Gets value as a long corresponding to the specified key. */
+    long getLong(String key);
 }
diff --git a/src/com/android/tv/config/RemoteConfigUtils.java b/src/com/android/tv/config/RemoteConfigUtils.java
new file mode 100644
index 0000000..09d8523
--- /dev/null
+++ b/src/com/android/tv/config/RemoteConfigUtils.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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.config;
+
+import android.content.Context;
+import android.util.Log;
+import com.android.tv.TvApplication;
+
+/** A utility class to get the remote config. */
+public class RemoteConfigUtils {
+    private static final String TAG = "RemoteConfigUtils";
+    private static final boolean DEBUG = false;
+
+    private RemoteConfigUtils() {}
+
+    public static long getRemoteConfig(Context context, String key, long defaultValue) {
+        RemoteConfig remoteConfig = TvApplication.getSingletons(context).getRemoteConfig();
+        try {
+            long remoteValue = remoteConfig.getLong(key);
+            if (DEBUG) Log.d(TAG, "Got " + key + " from remote: " + remoteValue);
+            return remoteValue;
+        } catch (Exception e) {
+            Log.w(TAG, "Cannot get " + key + " from RemoteConfig", e);
+        }
+        if (DEBUG) Log.d(TAG, "Use default value " + defaultValue);
+        return defaultValue;
+    }
+}
diff --git a/src/com/android/tv/customization/TvCustomizationManager.java b/src/com/android/tv/customization/TvCustomizationManager.java
index 22298a1..ed6b98c 100644
--- a/src/com/android/tv/customization/TvCustomizationManager.java
+++ b/src/com/android/tv/customization/TvCustomizationManager.java
@@ -18,15 +18,18 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
+import android.support.annotation.IntDef;
 import android.text.TextUtils;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -37,6 +40,10 @@
     private static final String TAG = "TvCustomizationManager";
     private static final boolean DEBUG = false;
 
+    private static final String[] CUSTOMIZE_PERMISSIONS = {
+            "com.android.tv.permission.CUSTOMIZE_TV_APP"
+    };
+
     private static final String CATEGORY_TV_CUSTOMIZATION =
             "com.android.tv.category";
 
@@ -47,6 +54,19 @@
     public static final String ID_OPTIONS_ROW = "options_row";
     public static final String ID_PARTNER_ROW = "partner_row";
 
+    @IntDef({TRICKPLAY_MODE_ENABLED, TRICKPLAY_MODE_DISABLED, TRICKPLAY_MODE_USE_EXTERNAL_STORAGE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TRICKPLAY_MODE {}
+    public static final int TRICKPLAY_MODE_ENABLED = 0;
+    public static final int TRICKPLAY_MODE_DISABLED = 1;
+    public static final int TRICKPLAY_MODE_USE_EXTERNAL_STORAGE = 2;
+
+    private static final String[] TRICKPLAY_MODE_STRINGS = {
+        "enabled",
+        "disabled",
+        "use_external_storage_only"
+    };
+
     private static final HashMap<String, String> INTENT_CATEGORY_TO_ROW_ID;
     static {
         INTENT_CATEGORY_TO_ROW_ID = new HashMap<>();
@@ -55,12 +75,19 @@
     }
 
     private static final String RES_ID_PARTNER_ROW_TITLE = "partner_row_title";
+    private static final String RES_ID_HAS_LINUX_DVB_BUILT_IN_TUNER =
+            "has_linux_dvb_built_in_tuner";
+    private static final String RES_ID_TRICKPLAY_MODE = "trickplay_mode";
 
     private static final String RES_TYPE_STRING = "string";
+    private static final String RES_TYPE_BOOLEAN = "bool";
+
+    private static String sCustomizationPackage;
+    private static Boolean sHasLinuxDvbBuiltInTuner;
+    private static @TRICKPLAY_MODE Integer sTrickplayMode;
 
     private final Context mContext;
     private boolean mInitialized;
-    private String mCustomizationPackage;
 
     private String mPartnerRowTitle;
     private final Map<String, List<CustomAction>> mRowIdToCustomActionsMap = new HashMap<>();
@@ -71,6 +98,68 @@
     }
 
     /**
+     * Returns {@code true} if there's a customization package installed and it specifies built-in
+     * tuner devices are available. The built-in tuner should support DVB API to be recognized by
+     * Live TV.
+     */
+    public static boolean hasLinuxDvbBuiltInTuner(Context context) {
+        if (sHasLinuxDvbBuiltInTuner == null) {
+            if (TextUtils.isEmpty(getCustomizationPackageName(context))) {
+                sHasLinuxDvbBuiltInTuner = false;
+            } else {
+                try {
+                    Resources res = context.getPackageManager()
+                            .getResourcesForApplication(sCustomizationPackage);
+                    int resId = res.getIdentifier(RES_ID_HAS_LINUX_DVB_BUILT_IN_TUNER,
+                            RES_TYPE_BOOLEAN, sCustomizationPackage);
+                    sHasLinuxDvbBuiltInTuner = resId != 0 && res.getBoolean(resId);
+                } catch (NameNotFoundException e) {
+                    sHasLinuxDvbBuiltInTuner = false;
+                }
+            }
+        }
+        return sHasLinuxDvbBuiltInTuner;
+    }
+
+    public static @TRICKPLAY_MODE int getTrickplayMode(Context context) {
+        if (sTrickplayMode == null) {
+            if (TextUtils.isEmpty(getCustomizationPackageName(context))) {
+                sTrickplayMode = TRICKPLAY_MODE_ENABLED;
+            } else {
+                try {
+                    String customization = null;
+                    Resources res = context.getPackageManager()
+                            .getResourcesForApplication(sCustomizationPackage);
+                    int resId = res.getIdentifier(RES_ID_TRICKPLAY_MODE,
+                            RES_TYPE_STRING, sCustomizationPackage);
+                    customization = resId == 0 ? null : res.getString(resId);
+                    sTrickplayMode = TRICKPLAY_MODE_ENABLED;
+                    if (customization != null) {
+                        for (int i = 0; i < TRICKPLAY_MODE_STRINGS.length; ++i) {
+                            if (TRICKPLAY_MODE_STRINGS[i].equalsIgnoreCase(customization)) {
+                                sTrickplayMode = i;
+                                break;
+                            }
+                        }
+                    }
+                } catch (NameNotFoundException e) {
+                    sTrickplayMode = TRICKPLAY_MODE_ENABLED;
+                }
+            }
+        }
+        return sTrickplayMode;
+    }
+
+    private static String getCustomizationPackageName(Context context) {
+        if (sCustomizationPackage == null) {
+            List<PackageInfo> packageInfos = context.getPackageManager()
+                    .getPackagesHoldingPermissions(CUSTOMIZE_PERMISSIONS, 0);
+            sCustomizationPackage = packageInfos.size() == 0 ? "" : packageInfos.get(0).packageName;
+        }
+        return sCustomizationPackage;
+    }
+
+    /**
      * Initialize TV customization options.
      * Run this API only on the main thread.
      */
@@ -79,14 +168,13 @@
             return;
         }
         mInitialized = true;
-        buildCustomActions();
-        if (!TextUtils.isEmpty(mCustomizationPackage)) {
+        if (!TextUtils.isEmpty(getCustomizationPackageName(mContext))) {
+            buildCustomActions();
             buildPartnerRow();
         }
     }
 
     private void buildCustomActions() {
-        mCustomizationPackage = null;
         mRowIdToCustomActionsMap.clear();
         PackageManager pm = mContext.getPackageManager();
         for (String intentCategory : INTENT_CATEGORY_TO_ROW_ID.keySet()) {
@@ -98,16 +186,8 @@
                             | PackageManager.GET_META_DATA);
             for (ResolveInfo info : activities) {
                 String packageName = info.activityInfo.packageName;
-                if (TextUtils.isEmpty(mCustomizationPackage)) {
-                    if (DEBUG) Log.d(TAG, "Found TV customization package " + packageName);
-                    if ((info.activityInfo.applicationInfo.flags
-                            & ApplicationInfo.FLAG_SYSTEM) == 0) {
-                        Log.w(TAG, "Only system app can customize TV. Ignoring " + packageName);
-                        continue;
-                    }
-                    mCustomizationPackage = packageName;
-                } else if (!packageName.equals(mCustomizationPackage)) {
-                    Log.w(TAG, "A customization package " + mCustomizationPackage
+                if (!TextUtils.equals(packageName, sCustomizationPackage)) {
+                    Log.w(TAG, "A customization package " + sCustomizationPackage
                             + " already exist. Ignoring " + packageName);
                     continue;
                 }
@@ -117,7 +197,7 @@
                 Drawable drawable = info.loadIcon(pm);
                 Intent intent = new Intent(Intent.ACTION_MAIN);
                 intent.addCategory(intentCategory);
-                intent.setClassName(mCustomizationPackage, info.activityInfo.name);
+                intent.setClassName(sCustomizationPackage, info.activityInfo.name);
 
                 String rowId = INTENT_CATEGORY_TO_ROW_ID.get(intentCategory);
                 List<CustomAction> actions = mRowIdToCustomActionsMap.get(rowId);
@@ -159,13 +239,13 @@
         Resources res;
         try {
             res = mContext.getPackageManager()
-                    .getResourcesForApplication(mCustomizationPackage);
+                    .getResourcesForApplication(sCustomizationPackage);
         } catch (NameNotFoundException e) {
-            Log.w(TAG, "Could not get resources for package " + mCustomizationPackage);
+            Log.w(TAG, "Could not get resources for package " + sCustomizationPackage);
             return;
         }
         int resId = res.getIdentifier(
-                RES_ID_PARTNER_ROW_TITLE, RES_TYPE_STRING, mCustomizationPackage);
+                RES_ID_PARTNER_ROW_TITLE, RES_TYPE_STRING, sCustomizationPackage);
         if (resId != 0) {
             mPartnerRowTitle = res.getString(resId);
         }
diff --git a/src/com/android/tv/data/BaseProgram.java b/src/com/android/tv/data/BaseProgram.java
index f420de0..4e36c80 100644
--- a/src/com/android/tv/data/BaseProgram.java
+++ b/src/com/android/tv/data/BaseProgram.java
@@ -17,12 +17,17 @@
 package com.android.tv.data;
 
 import android.content.Context;
+import android.media.tv.TvContentRating;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+
+import com.android.tv.R;
 
 import java.util.Comparator;
 
 /**
  * Base class for {@link com.android.tv.data.Program} and
- * {@link com.android.tv.dvr.RecordedProgram}.
+ * {@link com.android.tv.dvr.data.RecordedProgram}.
  */
 public abstract class BaseProgram {
     /**
@@ -94,14 +99,29 @@
     abstract public String getTitle();
 
     /**
-     * Returns the program's title withe its season and episode number.
+     * Returns the episode title.
      */
-    abstract public String getTitleWithEpisodeNumber(Context context);
+    abstract public String getEpisodeTitle();
 
     /**
      * Returns the displayed title of the program episode.
      */
-    abstract public String getEpisodeDisplayTitle(Context context);
+    public String getEpisodeDisplayTitle(Context context) {
+        if (!TextUtils.isEmpty(getEpisodeNumber())) {
+            String episodeTitle = getEpisodeTitle() == null ? "" : getEpisodeTitle();
+            if (TextUtils.equals(getSeasonNumber(), "0")) {
+                // Do not show "S0: ".
+                return String.format(context.getResources().getString(
+                        R.string.display_episode_title_format_no_season_number),
+                        getEpisodeNumber(), episodeTitle);
+            } else {
+                return String.format(context.getResources().getString(
+                        R.string.display_episode_title_format),
+                        getSeasonNumber(), getEpisodeNumber(), episodeTitle);
+            }
+        }
+        return getEpisodeTitle();
+    }
 
     /**
      * Returns the description of the program.
@@ -158,6 +178,10 @@
      */
     abstract public int[] getCanonicalGenreIds();
 
+    /** Returns the array of content ratings. */
+    @Nullable
+    abstract public TvContentRating[] getContentRatings();
+
     /**
      * Returns channel's ID of the program.
      */
@@ -169,6 +193,13 @@
     abstract public boolean isValid();
 
     /**
+     * Checks whether the program is episodic or not.
+     */
+    public boolean isEpisodic() {
+        return getSeriesId() != null;
+    }
+
+    /**
      * Generates the series ID for the other inputs than the tuner TV input.
      */
     public static String generateSeriesId(String packageName, String title) {
diff --git a/src/com/android/tv/data/Channel.java b/src/com/android/tv/data/Channel.java
index 30f8423..4a391ae 100644
--- a/src/com/android/tv/data/Channel.java
+++ b/src/com/android/tv/data/Channel.java
@@ -52,6 +52,16 @@
     public static final int LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART = 3;
 
     /**
+     * Compares the channel numbers of channels which belong to the same input.
+     */
+    public static final Comparator<Channel> CHANNEL_NUMBER_COMPARATOR = new Comparator<Channel>() {
+        @Override
+        public int compare(Channel lhs, Channel rhs) {
+            return ChannelNumber.compare(lhs.getDisplayNumber(), rhs.getDisplayNumber());
+        }
+    };
+
+    /**
      * When a TIS doesn't provide any information about app link, and it doesn't have a leanback
      * launch intent, there will be no app link card for the TIS.
      */
@@ -81,15 +91,22 @@
             TvContract.Channels.COLUMN_DESCRIPTION,
             TvContract.Channels.COLUMN_VIDEO_FORMAT,
             TvContract.Channels.COLUMN_BROWSABLE,
+            TvContract.Channels.COLUMN_SEARCHABLE,
             TvContract.Channels.COLUMN_LOCKED,
             TvContract.Channels.COLUMN_APP_LINK_TEXT,
             TvContract.Channels.COLUMN_APP_LINK_COLOR,
             TvContract.Channels.COLUMN_APP_LINK_ICON_URI,
             TvContract.Channels.COLUMN_APP_LINK_POSTER_ART_URI,
             TvContract.Channels.COLUMN_APP_LINK_INTENT_URI,
+            TvContract.Channels.COLUMN_INTERNAL_PROVIDER_FLAG2, // Only used in bundled input
     };
 
     /**
+     * Channel number delimiter between major and minor parts.
+     */
+    public static final char CHANNEL_NUMBER_DELIMITER = '-';
+
+    /**
      * Creates {@code Channel} object from cursor.
      *
      * <p>The query that created the cursor MUST use {@link #PROJECTION}
@@ -103,28 +120,41 @@
         channel.mPackageName = Utils.intern(cursor.getString(index++));
         channel.mInputId = Utils.intern(cursor.getString(index++));
         channel.mType = Utils.intern(cursor.getString(index++));
-        channel.mDisplayNumber = cursor.getString(index++);
+        channel.mDisplayNumber = normalizeDisplayNumber(cursor.getString(index++));
         channel.mDisplayName = cursor.getString(index++);
         channel.mDescription = cursor.getString(index++);
         channel.mVideoFormat = Utils.intern(cursor.getString(index++));
         channel.mBrowsable = cursor.getInt(index++) == 1;
+        channel.mSearchable = cursor.getInt(index++) == 1;
         channel.mLocked = cursor.getInt(index++) == 1;
         channel.mAppLinkText = cursor.getString(index++);
         channel.mAppLinkColor = cursor.getInt(index++);
         channel.mAppLinkIconUri = cursor.getString(index++);
         channel.mAppLinkPosterArtUri = cursor.getString(index++);
         channel.mAppLinkIntentUri = cursor.getString(index++);
+        if (Utils.isBundledInput(channel.mInputId)) {
+            channel.mRecordingProhibited = cursor.getInt(index++) != 0;
+        }
         return channel;
     }
 
     /**
-     * Creates a {@link Channel} object from the DVR database.
+     * Replaces the channel number separator with dash('-').
      */
-    public static Channel fromDvrCursor(Cursor c) {
-        Channel channel = new Channel();
-        int index = -1;
-        channel.mDvrId = c.getLong(++index);
-        return channel;
+    public static String normalizeDisplayNumber(String string) {
+        if (!TextUtils.isEmpty(string)) {
+            int length = string.length();
+            for (int i = 0; i < length; i++) {
+                char c = string.charAt(i);
+                if (c == '.' || Character.isWhitespace(c)
+                        || Character.getType(c) == Character.DASH_PUNCTUATION) {
+                    StringBuilder sb = new StringBuilder(string);
+                    sb.setCharAt(i, CHANNEL_NUMBER_DELIMITER);
+                    return sb.toString();
+                }
+            }
+        }
+        return string;
     }
 
     /** ID of this channel. Matches to BaseColumns._ID. */
@@ -138,6 +168,7 @@
     private String mDescription;
     private String mVideoFormat;
     private boolean mBrowsable;
+    private boolean mSearchable;
     private boolean mLocked;
     private boolean mIsPassthrough;
     private String mAppLinkText;
@@ -147,8 +178,10 @@
     private String mAppLinkIntentUri;
     private Intent mAppLinkIntent;
     private int mAppLinkType;
+    private String mLogoUri;
+    private boolean mRecordingProhibited;
 
-    private long mDvrId;
+    private boolean mChannelLogoExist;
 
     private Channel() {
         // Do nothing.
@@ -187,7 +220,6 @@
         return mDisplayName;
     }
 
-    @VisibleForTesting
     public String getDescription() {
         return mDescription;
     }
@@ -230,10 +262,14 @@
     }
 
     /**
-     * Returns an ID in DVR database.
+     * Returns channel logo uri which is got from cloud, it's used only for ChannelLogoFetcher.
      */
-    public long getDvrId() {
-        return mDvrId;
+    public String getLogoUri() {
+        return mLogoUri;
+    }
+
+    public boolean isRecordingProhibited() {
+        return mRecordingProhibited;
     }
 
     /**
@@ -266,6 +302,11 @@
         return mBrowsable;
     }
 
+    /** Checks whether this channel is searchable or not. */
+    public boolean isSearchable() {
+        return mSearchable;
+    }
+
     public boolean isLocked() {
         return mLocked;
     }
@@ -279,6 +320,13 @@
     }
 
     /**
+     * Sets channel logo uri which is got from cloud.
+     */
+    public void setLogoUri(String logoUri) {
+        mLogoUri = logoUri;
+    }
+
+    /**
      * Check whether {@code other} has same read-only channel info as this. But, it cannot check two
      * channels have same logos. It also excludes browsable and locked, because two fields are
      * changed by TV app.
@@ -298,7 +346,8 @@
                 && mAppLinkColor == other.mAppLinkColor
                 && Objects.equals(mAppLinkIconUri, other.mAppLinkIconUri)
                 && Objects.equals(mAppLinkPosterArtUri, other.mAppLinkPosterArtUri)
-                && Objects.equals(mAppLinkIntentUri, other.mAppLinkIntentUri);
+                && Objects.equals(mAppLinkIntentUri, other.mAppLinkIntentUri)
+                && Objects.equals(mRecordingProhibited, other.mRecordingProhibited);
     }
 
     @Override
@@ -314,8 +363,10 @@
                 + ", videoFormat=" + mVideoFormat
                 + ", isPassthrough=" + mIsPassthrough
                 + ", browsable=" + mBrowsable
+                + ", searchable=" + mSearchable
                 + ", locked=" + mLocked
-                + ", appLinkText=" + mAppLinkText + "}";
+                + ", appLinkText=" + mAppLinkText
+                + ", recordingProhibited=" + mRecordingProhibited + "}";
     }
 
     void copyFrom(Channel other) {
@@ -332,6 +383,7 @@
         mVideoFormat = other.mVideoFormat;
         mIsPassthrough = other.mIsPassthrough;
         mBrowsable = other.mBrowsable;
+        mSearchable = other.mSearchable;
         mLocked = other.mLocked;
         mAppLinkText = other.mAppLinkText;
         mAppLinkColor = other.mAppLinkColor;
@@ -340,6 +392,8 @@
         mAppLinkIntentUri = other.mAppLinkIntentUri;
         mAppLinkIntent = other.mAppLinkIntent;
         mAppLinkType = other.mAppLinkType;
+        mRecordingProhibited = other.mRecordingProhibited;
+        mChannelLogoExist = other.mChannelLogoExist;
     }
 
     /**
@@ -389,8 +443,7 @@
             mChannel.mDisplayName = "name";
             mChannel.mDescription = "description";
             mChannel.mBrowsable = true;
-            mChannel.mLocked = false;
-            mChannel.mIsPassthrough = false;
+            mChannel.mSearchable = true;
         }
 
         public Builder(Channel other) {
@@ -422,7 +475,7 @@
 
         @VisibleForTesting
         public Builder setDisplayNumber(String displayNumber) {
-            mChannel.mDisplayNumber = displayNumber;
+            mChannel.mDisplayNumber = normalizeDisplayNumber(displayNumber);
             return this;
         }
 
@@ -448,6 +501,11 @@
             return this;
         }
 
+        public Builder setSearchable(boolean searchable) {
+            mChannel.mSearchable = searchable;
+            return this;
+        }
+
         public Builder setLocked(boolean locked) {
             mChannel.mLocked = locked;
             return this;
@@ -485,6 +543,11 @@
             return this;
         }
 
+        public Builder setRecordingProhibited(boolean recordingProhibited) {
+            mChannel.mRecordingProhibited = recordingProhibited;
+            return this;
+        }
+
         public Channel build() {
             Channel channel = new Channel();
             channel.copyFrom(mChannel);
@@ -524,6 +587,21 @@
     }
 
     /**
+     * Sets if the channel logo exists. This method should be only called from
+     * {@link ChannelDataManager}.
+     */
+    void setChannelLogoExist(boolean exist) {
+        mChannelLogoExist = exist;
+    }
+
+    /**
+     * Returns if channel logo exists.
+     */
+    public boolean channelLogoExists() {
+        return mChannelLogoExist;
+    }
+
+    /**
      * Returns the type of app link for this channel.
      * It returns {@link #APP_LINK_TYPE_CHANNEL} if the channel has a non null app link text and
      * a valid app link intent, it returns {@link #APP_LINK_TYPE_APP} if the input service which
@@ -655,4 +733,4 @@
             return label;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/data/ChannelDataManager.java b/src/com/android/tv/data/ChannelDataManager.java
index 6f9ea6d..6f93fbd 100644
--- a/src/com/android/tv/data/ChannelDataManager.java
+++ b/src/com/android/tv/data/ChannelDataManager.java
@@ -21,13 +21,17 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.SharedPreferences.Editor;
+import android.content.res.AssetFileDescriptor;
 import android.database.ContentObserver;
+import android.database.sqlite.SQLiteException;
 import android.media.tv.TvContract;
 import android.media.tv.TvContract.Channels;
 import android.media.tv.TvInputManager.TvInputCallback;
+import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.support.annotation.AnyThread;
 import android.support.annotation.MainThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
@@ -43,6 +47,7 @@
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
 
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -59,7 +64,7 @@
  * This class is not thread-safe and under an assumption that its public methods are called in
  * only the main thread.
  */
-@MainThread
+@AnyThread
 public class ChannelDataManager {
     private static final String TAG = "ChannelDataManager";
     private static final boolean DEBUG = false;
@@ -74,10 +79,10 @@
     private final List<Runnable> mPostRunnablesAfterChannelUpdate = new ArrayList<>();
 
     private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
-    private final Map<Long, ChannelWrapper> mChannelWrapperMap = new HashMap<>();
-    private final Map<String, MutableInt> mChannelCountMap = new HashMap<>();
+    // Use container class to support multi-thread safety. This value can be set only on the main
+    // thread.
+    volatile private UnmodifiableChannelData mData = new UnmodifiableChannelData();
     private final Channel.DefaultComparator mChannelComparator;
-    private final List<Channel> mChannels = new ArrayList<>();
 
     private final Handler mHandler;
     private final Set<Long> mBrowsableUpdateChannelIds = new HashSet<>();
@@ -92,15 +97,17 @@
         @Override
         public void onInputAdded(String inputId) {
             boolean channelAdded = false;
-            for (ChannelWrapper channel : mChannelWrapperMap.values()) {
+            ChannelData data = new ChannelData(mData);
+            for (ChannelWrapper channel : mData.channelWrapperMap.values()) {
                 if (channel.mChannel.getInputId().equals(inputId)) {
                     channel.mInputRemoved = false;
-                    addChannel(channel.mChannel);
+                    addChannel(data, channel.mChannel);
                     channelAdded = true;
                 }
             }
             if (channelAdded) {
-                Collections.sort(mChannels, mChannelComparator);
+                Collections.sort(data.channels, mChannelComparator);
+                mData = new UnmodifiableChannelData(data);
                 notifyChannelListUpdated();
             }
         }
@@ -109,7 +116,7 @@
         public void onInputRemoved(String inputId) {
             boolean channelRemoved = false;
             ArrayList<ChannelWrapper> removedChannels = new ArrayList<>();
-            for (ChannelWrapper channel : mChannelWrapperMap.values()) {
+            for (ChannelWrapper channel : mData.channelWrapperMap.values()) {
                 if (channel.mChannel.getInputId().equals(inputId)) {
                     channel.mInputRemoved = true;
                     channelRemoved = true;
@@ -117,13 +124,15 @@
                 }
             }
             if (channelRemoved) {
-                clearChannels();
-                for (ChannelWrapper channelWrapper : mChannelWrapperMap.values()) {
+                ChannelData data = new ChannelData();
+                data.channelWrapperMap.putAll(mData.channelWrapperMap);
+                for (ChannelWrapper channelWrapper : data.channelWrapperMap.values()) {
                     if (!channelWrapper.mInputRemoved) {
-                        addChannel(channelWrapper.mChannel);
+                        addChannel(data, channelWrapper.mChannel);
                     }
                 }
-                Collections.sort(mChannels, mChannelComparator);
+                Collections.sort(data.channels, mChannelComparator);
+                mData = new UnmodifiableChannelData(data);
                 notifyChannelListUpdated();
                 for (ChannelWrapper channel : removedChannels) {
                     channel.notifyChannelRemoved();
@@ -132,10 +141,12 @@
         }
     };
 
+    @MainThread
     public ChannelDataManager(Context context, TvInputManagerHelper inputManager) {
         this(context, inputManager, context.getContentResolver());
     }
 
+    @MainThread
     @VisibleForTesting
     ChannelDataManager(Context context, TvInputManagerHelper inputManager,
             ContentResolver contentResolver) {
@@ -167,6 +178,7 @@
     /**
      * Starts the manager. If data is ready, {@link Listener#onLoadFinished()} will be called.
      */
+    @MainThread
     public void start() {
         if (mStarted) {
             return;
@@ -184,6 +196,7 @@
      * Stops the manager. It clears manager states and runs pending DB operations. Added listeners
      * aren't automatically removed by this method.
      */
+    @MainThread
     @VisibleForTesting
     public void stop() {
         if (!mStarted) {
@@ -192,12 +205,10 @@
         mStarted = false;
         mDbLoadFinished = false;
 
-        ChannelLogoFetcher.stopFetchingChannelLogos();
         mInputManager.removeCallback(mTvInputCallback);
         mContentResolver.unregisterContentObserver(mChannelObserver);
         mHandler.removeCallbacksAndMessages(null);
 
-        mChannelWrapperMap.clear();
         clearChannels();
         mPostRunnablesAfterChannelUpdate.clear();
         if (mChannelsUpdateTask != null) {
@@ -233,7 +244,7 @@
      * Adds a {@link ChannelListener} for a specific channel with the channel ID {@code channelId}.
      */
     public void addChannelListener(Long channelId, ChannelListener listener) {
-        ChannelWrapper channelWrapper = mChannelWrapperMap.get(channelId);
+        ChannelWrapper channelWrapper = mData.channelWrapperMap.get(channelId);
         if (channelWrapper == null) {
             return;
         }
@@ -245,7 +256,7 @@
      * {@code channelId}.
      */
     public void removeChannelListener(Long channelId, ChannelListener listener) {
-        ChannelWrapper channelWrapper = mChannelWrapperMap.get(channelId);
+        ChannelWrapper channelWrapper = mData.channelWrapperMap.get(channelId);
         if (channelWrapper == null) {
             return;
         }
@@ -263,14 +274,14 @@
      * Returns the number of channels.
      */
     public int getChannelCount() {
-        return mChannels.size();
+        return mData.channels.size();
     }
 
     /**
      * Returns a list of channels.
      */
     public List<Channel> getChannelList() {
-        return Collections.unmodifiableList(mChannels);
+        return new ArrayList<>(mData.channels);
     }
 
     /**
@@ -278,7 +289,7 @@
      */
     public List<Channel> getBrowsableChannelList() {
         List<Channel> channels = new ArrayList<>();
-        for (Channel channel : mChannels) {
+        for (Channel channel : mData.channels) {
             if (channel.isBrowsable()) {
                 channels.add(channel);
             }
@@ -292,7 +303,7 @@
      * @param inputId The ID of the input.
      */
     public int getChannelCountForInput(String inputId) {
-        MutableInt count = mChannelCountMap.get(inputId);
+        MutableInt count = mData.channelCountMap.get(inputId);
         return count == null ? 0 : count.value;
     }
 
@@ -303,17 +314,14 @@
      * In that case this method is used to check if the channel exists in the DB.
      */
     public boolean doesChannelExistInDb(long channelId) {
-        return mChannelWrapperMap.get(channelId) != null;
+        return mData.channelWrapperMap.get(channelId) != null;
     }
 
     /**
      * Returns true if and only if there exists at least one channel and all channels are hidden.
      */
     public boolean areAllChannelsHidden() {
-        if (mChannels.isEmpty()) {
-            return false;
-        }
-        for (Channel channel : mChannels) {
+        for (Channel channel : mData.channels) {
             if (channel.isBrowsable()) {
                 return false;
             }
@@ -325,7 +333,7 @@
      * Gets the channel with the channel ID {@code channelId}.
      */
     public Channel getChannel(Long channelId) {
-        ChannelWrapper channelWrapper = mChannelWrapperMap.get(channelId);
+        ChannelWrapper channelWrapper = mData.channelWrapperMap.get(channelId);
         if (channelWrapper == null || channelWrapper.mInputRemoved) {
             return null;
         }
@@ -349,7 +357,7 @@
      */
     public void updateBrowsable(Long channelId, boolean browsable,
             boolean skipNotifyChannelBrowsableChanged) {
-        ChannelWrapper channelWrapper = mChannelWrapperMap.get(channelId);
+        ChannelWrapper channelWrapper = mData.channelWrapperMap.get(channelId);
         if (channelWrapper == null) {
             return;
         }
@@ -407,7 +415,7 @@
      * The value change will be applied to DB when applyPendingDbOperation is called.
      */
     public void updateLocked(Long channelId, boolean locked) {
-        ChannelWrapper channelWrapper = mChannelWrapperMap.get(channelId);
+        ChannelWrapper channelWrapper = mData.channelWrapperMap.get(channelId);
         if (channelWrapper == null) {
             return;
         }
@@ -427,10 +435,11 @@
      * to DB.
      */
     public void applyUpdatedValuesToDb() {
+        ChannelData data = mData;
         ArrayList<Long> browsableIds = new ArrayList<>();
         ArrayList<Long> unbrowsableIds = new ArrayList<>();
         for (Long id : mBrowsableUpdateChannelIds) {
-            ChannelWrapper channelWrapper = mChannelWrapperMap.get(id);
+            ChannelWrapper channelWrapper = data.channelWrapperMap.get(id);
             if (channelWrapper == null) {
                 continue;
             }
@@ -452,10 +461,10 @@
             }
             editor.apply();
         } else {
-            if (browsableIds.size() != 0) {
+            if (!browsableIds.isEmpty()) {
                 updateOneColumnValue(column, 1, browsableIds);
             }
-            if (unbrowsableIds.size() != 0) {
+            if (!unbrowsableIds.isEmpty()) {
                 updateOneColumnValue(column, 0, unbrowsableIds);
             }
         }
@@ -464,7 +473,7 @@
         ArrayList<Long> lockedIds = new ArrayList<>();
         ArrayList<Long> unlockedIds = new ArrayList<>();
         for (Long id : mLockedUpdateChannelIds) {
-            ChannelWrapper channelWrapper = mChannelWrapperMap.get(id);
+            ChannelWrapper channelWrapper = data.channelWrapperMap.get(id);
             if (channelWrapper == null) {
                 continue;
             }
@@ -476,10 +485,10 @@
             channelWrapper.mLockedInDb = channelWrapper.mChannel.isLocked();
         }
         column = TvContract.Channels.COLUMN_LOCKED;
-        if (lockedIds.size() != 0) {
+        if (!lockedIds.isEmpty()) {
             updateOneColumnValue(column, 1, lockedIds);
         }
-        if (unlockedIds.size() != 0) {
+        if (!unlockedIds.isEmpty()) {
             updateOneColumnValue(column, 0, unlockedIds);
         }
         mLockedUpdateChannelIds.clear();
@@ -492,22 +501,24 @@
         }
     }
 
-    private void addChannel(Channel channel) {
-        mChannels.add(channel);
+    @MainThread
+    private void addChannel(ChannelData data, Channel channel) {
+        data.channels.add(channel);
         String inputId = channel.getInputId();
-        MutableInt count = mChannelCountMap.get(inputId);
+        MutableInt count = data.channelCountMap.get(inputId);
         if (count == null) {
-            mChannelCountMap.put(inputId, new MutableInt(1));
+            data.channelCountMap.put(inputId, new MutableInt(1));
         } else {
             count.value++;
         }
     }
 
+    @MainThread
     private void clearChannels() {
-        mChannels.clear();
-        mChannelCountMap.clear();
+        mData = new UnmodifiableChannelData();
     }
 
+    @MainThread
     private void handleUpdateChannels() {
         if (mChannelsUpdateTask != null) {
             mChannelsUpdateTask.cancel(true);
@@ -525,6 +536,9 @@
         }
     }
 
+    /**
+     * A listener for ChannelDataManager. The callbacks are called on the main thread.
+     */
     public interface Listener {
         /**
          * Called when data load is finished.
@@ -543,6 +557,9 @@
         void onChannelBrowsableChanged();
     }
 
+    /**
+     * A listener for individual channel change. The callbacks are called on the main thread.
+     */
     public interface ChannelListener {
         /**
          * Called when the channel has been removed in DB.
@@ -590,9 +607,36 @@
         }
     }
 
+    private class CheckChannelLogoExistTask extends AsyncTask<Void, Void, Boolean> {
+        private final Channel mChannel;
+
+        CheckChannelLogoExistTask(Channel channel) {
+            mChannel = channel;
+        }
+
+        @Override
+        protected Boolean doInBackground(Void... params) {
+            try (AssetFileDescriptor f = mContext.getContentResolver().openAssetFileDescriptor(
+                        TvContract.buildChannelLogoUri(mChannel.getId()), "r")) {
+                return true;
+            } catch (SQLiteException | IOException | NullPointerException e) {
+                // File not found or asset file not found.
+            }
+            return false;
+        }
+
+        @Override
+        protected void onPostExecute(Boolean result) {
+            ChannelWrapper wrapper = mData.channelWrapperMap.get(mChannel.getId());
+            if (wrapper != null) {
+                wrapper.mChannel.setChannelLogoExist(result);
+            }
+        }
+    }
+
     private final class QueryAllChannelsTask extends AsyncDbTask.AsyncChannelQueryTask {
 
-        public QueryAllChannelsTask(ContentResolver contentResolver) {
+        QueryAllChannelsTask(ContentResolver contentResolver) {
             super(contentResolver);
         }
 
@@ -603,7 +647,9 @@
                 if (DEBUG) Log.e(TAG, "onPostExecute with null channels");
                 return;
             }
-            Set<Long> removedChannelIds = new HashSet<>(mChannelWrapperMap.keySet());
+            ChannelData data = new ChannelData();
+            data.channelWrapperMap.putAll(mData.channelWrapperMap);
+            Set<Long> removedChannelIds = new HashSet<>(data.channelWrapperMap.keySet());
             List<ChannelWrapper> removedChannelWrappers = new ArrayList<>();
             List<ChannelWrapper> updatedChannelWrappers = new ArrayList<>();
 
@@ -625,13 +671,15 @@
                 boolean newlyAdded = !removedChannelIds.remove(channelId);
                 ChannelWrapper channelWrapper;
                 if (newlyAdded) {
+                    new CheckChannelLogoExistTask(channel)
+                            .executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
                     channelWrapper = new ChannelWrapper(channel);
-                    mChannelWrapperMap.put(channel.getId(), channelWrapper);
+                    data.channelWrapperMap.put(channel.getId(), channelWrapper);
                     if (!channelWrapper.mInputRemoved) {
                         channelAdded = true;
                     }
                 } else {
-                    channelWrapper = mChannelWrapperMap.get(channelId);
+                    channelWrapper = data.channelWrapperMap.get(channelId);
                     if (!channelWrapper.mChannel.hasSameReadOnlyInfo(channel)) {
                         // Channel data updated
                         Channel oldChannel = channelWrapper.mChannel;
@@ -640,9 +688,9 @@
                         // {@link #applyUpdatedValuesToDb} is called. Therefore, the value
                         // between DB and ChannelDataManager could be different for a while.
                         // Therefore, we'll keep the values in ChannelDataManager.
-                        channelWrapper.mChannel.copyFrom(channel);
                         channel.setBrowsable(oldChannel.isBrowsable());
                         channel.setLocked(oldChannel.isLocked());
+                        channelWrapper.mChannel.copyFrom(channel);
                         if (!channelWrapper.mInputRemoved) {
                             channelUpdated = true;
                             updatedChannelWrappers.add(channelWrapper);
@@ -663,19 +711,19 @@
             }
 
             for (long id : removedChannelIds) {
-                ChannelWrapper channelWrapper = mChannelWrapperMap.remove(id);
+                ChannelWrapper channelWrapper = data.channelWrapperMap.remove(id);
                 if (!channelWrapper.mInputRemoved) {
                     channelRemoved = true;
                     removedChannelWrappers.add(channelWrapper);
                 }
             }
-            clearChannels();
-            for (ChannelWrapper channelWrapper : mChannelWrapperMap.values()) {
+            for (ChannelWrapper channelWrapper : data.channelWrapperMap.values()) {
                 if (!channelWrapper.mInputRemoved) {
-                    addChannel(channelWrapper.mChannel);
+                    addChannel(data, channelWrapper.mChannel);
                 }
             }
-            Collections.sort(mChannels, mChannelComparator);
+            Collections.sort(data.channels, mChannelComparator);
+            mData = new UnmodifiableChannelData(data);
 
             if (!mDbLoadFinished) {
                 mDbLoadFinished = true;
@@ -693,7 +741,6 @@
                 r.run();
             }
             mPostRunnablesAfterChannelUpdate.clear();
-            ChannelLogoFetcher.startFetchingChannelLogos(mContext);
         }
     }
 
@@ -705,10 +752,9 @@
     private void updateOneColumnValue(
             final String columnName, final int columnValue, final List<Long> ids) {
         if (!PermissionUtils.hasAccessAllEpg(mContext)) {
-            // TODO: support this feature for non-system LC app. b/23939816
             return;
         }
-        AsyncDbTask.execute(new Runnable() {
+        AsyncDbTask.executeOnDbThread(new Runnable() {
             @Override
             public void run() {
                 String selection = Utils.buildSelectionForIds(Channels._ID, ids);
@@ -723,6 +769,7 @@
         return channel.getInputId() + "|" + channel.getId();
     }
 
+    @MainThread
     private static class ChannelDataManagerHandler extends WeakHandler<ChannelDataManager> {
         public ChannelDataManagerHandler(ChannelDataManager channelDataManager) {
             super(Looper.getMainLooper(), channelDataManager);
@@ -735,4 +782,51 @@
             }
         }
     }
+
+    /**
+     * Container class which includes channel data that needs to be synced. This class is
+     * modifiable and used for changing channel data.
+     * e.g. TvInputCallback, or AsyncDbTask.onPostExecute.
+     */
+    @MainThread
+    private static class ChannelData {
+        final Map<Long, ChannelWrapper> channelWrapperMap;
+        final Map<String, MutableInt> channelCountMap;
+        final List<Channel> channels;
+
+        ChannelData() {
+            channelWrapperMap = new HashMap<>();
+            channelCountMap = new HashMap<>();
+            channels = new ArrayList<>();
+        }
+
+        ChannelData(ChannelData data) {
+            channelWrapperMap = new HashMap<>(data.channelWrapperMap);
+            channelCountMap = new HashMap<>(data.channelCountMap);
+            channels = new ArrayList<>(data.channels);
+        }
+
+        ChannelData(Map<Long, ChannelWrapper> channelWrapperMap,
+                Map<String, MutableInt> channelCountMap, List<Channel> channels) {
+            this.channelWrapperMap = channelWrapperMap;
+            this.channelCountMap = channelCountMap;
+            this.channels = channels;
+        }
+    }
+
+    /** Unmodifiable channel data. */
+    @MainThread
+    private static class UnmodifiableChannelData extends ChannelData {
+        UnmodifiableChannelData() {
+            super(Collections.unmodifiableMap(new HashMap<>()),
+                    Collections.unmodifiableMap(new HashMap<>()),
+                    Collections.unmodifiableList(new ArrayList<>()));
+        }
+
+        UnmodifiableChannelData(ChannelData data) {
+            super(Collections.unmodifiableMap(data.channelWrapperMap),
+                    Collections.unmodifiableMap(data.channelCountMap),
+                    Collections.unmodifiableList(data.channels));
+        }
+    }
 }
diff --git a/src/com/android/tv/data/ChannelLogoFetcher.java b/src/com/android/tv/data/ChannelLogoFetcher.java
index 5a549f8..132cab7 100644
--- a/src/com/android/tv/data/ChannelLogoFetcher.java
+++ b/src/com/android/tv/data/ChannelLogoFetcher.java
@@ -16,160 +16,74 @@
 
 package com.android.tv.data;
 
+import android.content.ContentProviderOperation;
 import android.content.Context;
-import android.database.Cursor;
+import android.content.OperationApplicationException;
+import android.content.SharedPreferences;
 import android.graphics.Bitmap.CompressFormat;
 import android.media.tv.TvContract;
-import android.media.tv.TvContract.Channels;
 import android.net.Uri;
 import android.os.AsyncTask;
-import android.support.annotation.WorkerThread;
+import android.os.RemoteException;
+import android.support.annotation.MainThread;
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.tv.util.AsyncDbTask;
+import com.android.tv.common.SharedPreferencesUtils;
 import com.android.tv.util.BitmapUtils;
 import com.android.tv.util.BitmapUtils.ScaledBitmapInfo;
 import com.android.tv.util.PermissionUtils;
 
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Locale;
 import java.util.Map;
-import java.util.Set;
+import java.util.List;
 
 /**
- * Utility class for TMS data.
- * This class is thread safe.
+ * Fetches channel logos from the cloud into the database. It's for the channels which have no logos
+ * or need update logos. This class is thread safe.
  */
 public class ChannelLogoFetcher {
     private static final String TAG = "ChannelLogoFetcher";
     private static final boolean DEBUG = false;
 
-    /**
-     * The name of the file which contains the TMS data.
-     * The file has multiple records and each of them is a string separated by '|' like
-     * STATION_NAME|SHORT_NAME|CALL_SIGN|LOGO_URI.
-     */
-    private static final String TMS_US_TABLE_FILE = "tms_us.table";
-    private static final String TMS_KR_TABLE_FILE = "tms_kr.table";
-    private static final String FIELD_SEPARATOR = "\\|";
-    private static final String NAME_SEPARATOR_FOR_TMS = "\\(|\\)|\\{|\\}|\\[|\\]";
-    private static final String NAME_SEPARATOR_FOR_DB = "\\W";
-    private static final int INDEX_NAME = 0;
-    private static final int INDEX_SHORT_NAME = 1;
-    private static final int INDEX_CALL_SIGN = 2;
-    private static final int INDEX_LOGO_URI = 3;
+    private static final String PREF_KEY_IS_FIRST_TIME_FETCH_CHANNEL_LOGO =
+            "is_first_time_fetch_channel_logo";
 
-    private static final String COLUMN_CHANNEL_LOGO = "logo";
-
-    private static final Object sLock = new Object();
-    private static final Set<Long> sChannelIdBlackListSet = new HashSet<>();
-    private static LoadChannelTask sQueryTask;
     private static FetchLogoTask sFetchTask;
 
     /**
-     * Fetch the channel logos from TMS data and insert them into TvProvider.
+     * Fetches the channel logos from the cloud data and insert them into TvProvider.
      * The previous task is canceled and a new task starts.
      */
-    public static void startFetchingChannelLogos(Context context) {
+    @MainThread
+    public static void startFetchingChannelLogos(
+            Context context, List<Channel> channels) {
         if (!PermissionUtils.hasAccessAllEpg(context)) {
             // TODO: support this feature for non-system LC app. b/23939816
             return;
         }
-        synchronized (sLock) {
-            stopFetchingChannelLogos();
-            if (DEBUG) Log.d(TAG, "Request to start fetching logos.");
-            sQueryTask = new LoadChannelTask(context);
-            sQueryTask.executeOnDbThread();
+        if (sFetchTask != null) {
+            sFetchTask.cancel(true);
+            sFetchTask = null;
         }
-    }
-
-    /**
-     * Stops the current fetching tasks. This can be called when the Activity pauses.
-     */
-    public static void stopFetchingChannelLogos() {
-        synchronized (sLock) {
-            if (DEBUG) Log.d(TAG, "Request to stop fetching logos.");
-            if (sQueryTask != null) {
-                sQueryTask.cancel(true);
-                sQueryTask = null;
-            }
-            if (sFetchTask != null) {
-                sFetchTask.cancel(true);
-                sFetchTask = null;
-            }
+        if (DEBUG) Log.d(TAG, "Request to start fetching logos.");
+        if (channels == null || channels.isEmpty()) {
+            return;
         }
+        sFetchTask = new FetchLogoTask(context.getApplicationContext(), channels);
+        sFetchTask.execute();
     }
 
     private ChannelLogoFetcher() {
     }
 
-    private static final class LoadChannelTask extends AsyncDbTask<Void, Void, List<Channel>> {
-        private final Context mContext;
-
-        public LoadChannelTask(Context context) {
-            mContext = context;
-        }
-
-        @Override
-        protected List<Channel> doInBackground(Void... arg) {
-            // Load channels which doesn't have channel logos.
-            if (DEBUG) Log.d(TAG, "Starts loading the channels from DB");
-            String[] projection =
-                    new String[] { Channels._ID, Channels.COLUMN_DISPLAY_NAME };
-            String selection = COLUMN_CHANNEL_LOGO + " IS NULL AND "
-                    + Channels.COLUMN_PACKAGE_NAME + "=?";
-            String[] selectionArgs = new String[] { mContext.getPackageName() };
-            try (Cursor c = mContext.getContentResolver().query(Channels.CONTENT_URI,
-                    projection, selection, selectionArgs, null)) {
-                if (c == null) {
-                    Log.e(TAG, "Query returns null cursor", new RuntimeException());
-                    return null;
-                }
-                List<Channel> channels = new ArrayList<>();
-                while (!isCancelled() && c.moveToNext()) {
-                    long channelId = c.getLong(0);
-                    if (sChannelIdBlackListSet.contains(channelId)) {
-                        continue;
-                    }
-                    channels.add(new Channel.Builder().setId(c.getLong(0))
-                            .setDisplayName(c.getString(1).toUpperCase(Locale.getDefault()))
-                            .build());
-                }
-                return channels;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(List<Channel> channels) {
-            synchronized (sLock) {
-                if (DEBUG) {
-                    int count = channels == null ? 0 : channels.size();
-                    Log.d(TAG, count + " channels are loaded");
-                }
-                if (sQueryTask == this) {
-                    sQueryTask = null;
-                    if (channels != null && !channels.isEmpty()) {
-                        sFetchTask = new FetchLogoTask(mContext, channels);
-                        sFetchTask.execute();
-                    }
-                }
-            }
-        }
-    }
-
     private static final class FetchLogoTask extends AsyncTask<Void, Void, Void> {
         private final Context mContext;
         private final List<Channel> mChannels;
 
-        public FetchLogoTask(Context context, List<Channel> channels) {
+        private FetchLogoTask(Context context, List<Channel> channels) {
             mContext = context;
             mChannels = channels;
         }
@@ -180,83 +94,53 @@
                 if (DEBUG) Log.d(TAG, "Fetching the channel logos has been canceled");
                 return null;
             }
-            // Load the TMS table data.
-            if (DEBUG) Log.d(TAG, "Loads TMS data");
-            Map<String, String> channelNameLogoUriMap = new HashMap<>();
-            try {
-                channelNameLogoUriMap.putAll(readTmsFile(mContext, TMS_US_TABLE_FILE));
-                if (isCancelled()) {
-                    if (DEBUG) Log.d(TAG, "Fetching the channel logos has been canceled");
-                    return null;
-                }
-                channelNameLogoUriMap.putAll(readTmsFile(mContext, TMS_KR_TABLE_FILE));
-            } catch (IOException e) {
-                Log.e(TAG, "Loading TMS data failed.", e);
-                return null;
-            }
-            if (isCancelled()) {
-                if (DEBUG) Log.d(TAG, "Fetching the channel logos has been canceled");
-                return null;
-            }
-
+            List<Channel> channelsToUpdate = new ArrayList<>();
+            List<Channel> channelsToRemove = new ArrayList<>();
+            // Updates or removes the logo by comparing the logo uri which is got from the cloud
+            // and the stored one. And we assume that the data got form the cloud is 100%
+            // correct and completed.
+            SharedPreferences sharedPreferences =
+                    mContext.getSharedPreferences(
+                            SharedPreferencesUtils.SHARED_PREF_CHANNEL_LOGO_URIS,
+                            Context.MODE_PRIVATE);
+            SharedPreferences.Editor sharedPreferencesEditor = sharedPreferences.edit();
+            Map<String, ?> uncheckedChannels = sharedPreferences.getAll();
+            boolean isFirstTimeFetchChannelLogo = sharedPreferences.getBoolean(
+                    PREF_KEY_IS_FIRST_TIME_FETCH_CHANNEL_LOGO, true);
             // Iterating channels.
             for (Channel channel : mChannels) {
+                String channelIdString = Long.toString(channel.getId());
+                String storedChannelLogoUri = (String) uncheckedChannels.remove(channelIdString);
+                if (!TextUtils.isEmpty(channel.getLogoUri())
+                        && !TextUtils.equals(storedChannelLogoUri, channel.getLogoUri())) {
+                    channelsToUpdate.add(channel);
+                    sharedPreferencesEditor.putString(channelIdString, channel.getLogoUri());
+                } else if (TextUtils.isEmpty(channel.getLogoUri())
+                        && (!TextUtils.isEmpty(storedChannelLogoUri)
+                        || isFirstTimeFetchChannelLogo)) {
+                    channelsToRemove.add(channel);
+                    sharedPreferencesEditor.remove(channelIdString);
+                }
+            }
+
+            // Removes non existing channels from SharedPreferences.
+            for (String channelId : uncheckedChannels.keySet()) {
+                sharedPreferencesEditor.remove(channelId);
+            }
+
+            // Updates channel logos.
+            for (Channel channel : channelsToUpdate) {
                 if (isCancelled()) {
                     if (DEBUG) Log.d(TAG, "Fetching the channel logos has been canceled");
                     return null;
                 }
-                // Download the channel logo.
-                if (TextUtils.isEmpty(channel.getDisplayName())) {
-                    if (DEBUG) {
-                        Log.d(TAG, "The channel with ID (" + channel.getId()
-                                + ") doesn't have the display name.");
-                    }
-                    sChannelIdBlackListSet.add(channel.getId());
-                    continue;
-                }
-                String channelName = channel.getDisplayName().trim();
-                String logoUri = channelNameLogoUriMap.get(channelName);
-                if (TextUtils.isEmpty(logoUri)) {
-                    if (DEBUG) {
-                        Log.d(TAG, "Can't find a logo URI for channel '" + channelName + "'");
-                    }
-                    // Find the candidate names. If the channel name is CNN-HD, then find CNNHD
-                    // and CNN. Or if the channel name is KQED+, then find KQED.
-                    String[] splitNames = channelName.split(NAME_SEPARATOR_FOR_DB);
-                    if (splitNames.length > 1) {
-                        StringBuilder sb = new StringBuilder();
-                        for (String splitName : splitNames) {
-                            sb.append(splitName);
-                        }
-                        logoUri = channelNameLogoUriMap.get(sb.toString());
-                        if (DEBUG) {
-                            if (TextUtils.isEmpty(logoUri)) {
-                                Log.d(TAG, "Can't find a logo URI for channel '" + sb.toString()
-                                        + "'");
-                            }
-                        }
-                    }
-                    if (TextUtils.isEmpty(logoUri)
-                            && splitNames[0].length() != channelName.length()) {
-                        logoUri = channelNameLogoUriMap.get(splitNames[0]);
-                        if (DEBUG) {
-                            if (TextUtils.isEmpty(logoUri)) {
-                                Log.d(TAG, "Can't find a logo URI for channel '" + splitNames[0]
-                                        + "'");
-                            }
-                        }
-                    }
-                }
-                if (TextUtils.isEmpty(logoUri)) {
-                    sChannelIdBlackListSet.add(channel.getId());
-                    continue;
-                }
+                // Downloads the channel logo.
+                String logoUri = channel.getLogoUri();
                 ScaledBitmapInfo bitmapInfo = BitmapUtils.decodeSampledBitmapFromUriString(
                         mContext, logoUri, Integer.MAX_VALUE, Integer.MAX_VALUE);
                 if (bitmapInfo == null) {
                     Log.e(TAG, "Failed to load bitmap. {channelName=" + channel.getDisplayName()
                             + ", " + "logoUri=" + logoUri + "}");
-                    sChannelIdBlackListSet.add(channel.getId());
                     continue;
                 }
                 if (isCancelled()) {
@@ -264,12 +148,15 @@
                     return null;
                 }
 
-                // Insert the logo to DB.
+                // Inserts the logo to DB.
                 Uri dstLogoUri = TvContract.buildChannelLogoUri(channel.getId());
                 try (OutputStream os = mContext.getContentResolver().openOutputStream(dstLogoUri)) {
                     bitmapInfo.bitmap.compress(CompressFormat.PNG, 100, os);
                 } catch (IOException e) {
                     Log.e(TAG, "Failed to write " + logoUri + "  to " + dstLogoUri, e);
+                    // Removes it from the shared preference for the failed channels to make it
+                    // retry next time.
+                    sharedPreferencesEditor.remove(Long.toString(channel.getId()));
                     continue;
                 }
                 if (DEBUG) {
@@ -277,63 +164,35 @@
                             + dstLogoUri + "}");
                 }
             }
+
+            // Removes the logos for the channels that have logos before but now
+            // their logo uris are null.
+            boolean deleteChannelLogoFailed = false;
+            if (!channelsToRemove.isEmpty()) {
+                ArrayList<ContentProviderOperation> ops = new ArrayList<>();
+                for (Channel channel : channelsToRemove) {
+                    ops.add(ContentProviderOperation.newDelete(
+                        TvContract.buildChannelLogoUri(channel.getId())).build());
+                }
+                try {
+                    mContext.getContentResolver().applyBatch(TvContract.AUTHORITY, ops);
+                } catch (RemoteException | OperationApplicationException e) {
+                    deleteChannelLogoFailed = true;
+                    Log.e(TAG, "Error deleting obsolete channels", e);
+                }
+            }
+            if (isFirstTimeFetchChannelLogo && !deleteChannelLogoFailed) {
+                sharedPreferencesEditor.putBoolean(
+                        PREF_KEY_IS_FIRST_TIME_FETCH_CHANNEL_LOGO, false);
+            }
+            sharedPreferencesEditor.commit();
             if (DEBUG) Log.d(TAG, "Fetching logos has been finished successfully.");
             return null;
         }
 
-        @WorkerThread
-        private Map<String, String> readTmsFile(Context context, String fileName)
-                throws IOException {
-            try (BufferedReader reader = new BufferedReader(new InputStreamReader(
-                    context.getAssets().open(fileName)))) {
-                Map<String, String> channelNameLogoUriMap = new HashMap<>();
-                String line;
-                while ((line = reader.readLine()) != null && !isCancelled()) {
-                    String[] data = line.split(FIELD_SEPARATOR);
-                    if (data.length != INDEX_LOGO_URI + 1) {
-                        if (DEBUG) Log.d(TAG, "Invalid or comment row: " + line);
-                        continue;
-                    }
-                    addChannelNames(channelNameLogoUriMap,
-                            data[INDEX_NAME].toUpperCase(Locale.getDefault()),
-                            data[INDEX_LOGO_URI]);
-                    addChannelNames(channelNameLogoUriMap,
-                            data[INDEX_SHORT_NAME].toUpperCase(Locale.getDefault()),
-                            data[INDEX_LOGO_URI]);
-                    addChannelNames(channelNameLogoUriMap,
-                            data[INDEX_CALL_SIGN].toUpperCase(Locale.getDefault()),
-                            data[INDEX_LOGO_URI]);
-                }
-                return channelNameLogoUriMap;
-            }
-        }
-
-        private void addChannelNames(Map<String, String> channelNameLogoUriMap, String channelName,
-                String logoUri) {
-            if (!TextUtils.isEmpty(channelName)) {
-                channelNameLogoUriMap.put(channelName, logoUri);
-                // Find the candidate names.
-                // If the name is like "W05AAD (W05AA-D)", then split the names into "W05AAD" and
-                // "W05AA-D"
-                String[] splitNames = channelName.split(NAME_SEPARATOR_FOR_TMS);
-                if (splitNames.length > 1) {
-                    for (String name : splitNames) {
-                        name = name.trim();
-                        if (channelNameLogoUriMap.get(name) == null) {
-                            channelNameLogoUriMap.put(name, logoUri);
-                        }
-                    }
-                }
-            }
-        }
-
         @Override
         protected void onPostExecute(Void result) {
-            synchronized (sLock) {
-                if (sFetchTask == this) {
-                    sFetchTask = null;
-                }
-            }
+            sFetchTask = null;
         }
     }
 }
diff --git a/src/com/android/tv/data/ChannelNumber.java b/src/com/android/tv/data/ChannelNumber.java
index 5902160..29054aa 100644
--- a/src/com/android/tv/data/ChannelNumber.java
+++ b/src/com/android/tv/data/ChannelNumber.java
@@ -17,37 +17,38 @@
 package com.android.tv.data;
 
 import android.support.annotation.NonNull;
+import android.text.TextUtils;
 import android.view.KeyEvent;
 
+import com.android.tv.util.StringUtils;
+
+import java.util.Objects;
+
 /**
  * A convenience class to handle channel number.
  */
 public final class ChannelNumber implements Comparable<ChannelNumber> {
-    public static final String PRIMARY_CHANNEL_DELIMITER = "-";
-    public static final String[] CHANNEL_DELIMITERS = {"-", ".", " "};
-
     private static final int[] CHANNEL_DELIMITER_KEYCODES = {
         KeyEvent.KEYCODE_MINUS, KeyEvent.KEYCODE_NUMPAD_SUBTRACT, KeyEvent.KEYCODE_PERIOD,
         KeyEvent.KEYCODE_NUMPAD_DOT, KeyEvent.KEYCODE_SPACE
     };
 
+    /** The major part of the channel number. */
     public String majorNumber;
+    /** The flag which indicates whether it has a delimiter or not. */
     public boolean hasDelimiter;
+    /** The major part of the channel number. */
     public String minorNumber;
 
     public ChannelNumber() {
         reset();
     }
 
-    public ChannelNumber(String major, boolean hasDelimiter, String minor) {
-        setChannelNumber(major, hasDelimiter, minor);
-    }
-
     public void reset() {
         setChannelNumber("", false, "");
     }
 
-    public void setChannelNumber(String majorNumber, boolean hasDelimiter, String minorNumber) {
+    private void setChannelNumber(String majorNumber, boolean hasDelimiter, String minorNumber) {
         this.majorNumber = majorNumber;
         this.hasDelimiter = hasDelimiter;
         this.minorNumber = minorNumber;
@@ -56,7 +57,7 @@
     @Override
     public String toString() {
         if (hasDelimiter) {
-            return majorNumber + PRIMARY_CHANNEL_DELIMITER + minorNumber;
+            return majorNumber + Channel.CHANNEL_NUMBER_DELIMITER + minorNumber;
         }
         return majorNumber;
     }
@@ -75,6 +76,22 @@
         return major - opponentMajor;
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof ChannelNumber) {
+            ChannelNumber channelNumber = (ChannelNumber) obj;
+            return TextUtils.equals(majorNumber, channelNumber.majorNumber)
+                    && TextUtils.equals(minorNumber, channelNumber.minorNumber)
+                    && hasDelimiter == channelNumber.hasDelimiter;
+        }
+        return super.equals(obj);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(majorNumber, hasDelimiter, minorNumber);
+    }
+
     public static boolean isChannelNumberDelimiterKey(int keyCode) {
         for (int delimiterKeyCode : CHANNEL_DELIMITER_KEYCODES) {
             if (delimiterKeyCode == keyCode) {
@@ -84,22 +101,22 @@
         return false;
     }
 
+    /**
+     * Returns the ChannelNumber instance.
+     * <p>
+     * Note that all the channel number argument should be normalized by
+     * {@link Channel#normalizeDisplayNumber}. The channels retrieved from
+     * {@link ChannelDataManager} are already normalized.
+     */
     public static ChannelNumber parseChannelNumber(String number) {
         if (number == null) {
             return null;
         }
         ChannelNumber ret = new ChannelNumber();
-        int indexOfDelimiter = -1;
-        for (String delimiter : CHANNEL_DELIMITERS) {
-            indexOfDelimiter = number.indexOf(delimiter);
-            if (indexOfDelimiter >= 0) {
-                break;
-            }
-        }
+        int indexOfDelimiter = number.indexOf(Channel.CHANNEL_NUMBER_DELIMITER);
         if (indexOfDelimiter == 0 || indexOfDelimiter == number.length() - 1) {
             return null;
-        }
-        if (indexOfDelimiter < 0) {
+        } else if (indexOfDelimiter < 0) {
             ret.majorNumber = number;
             if (!isInteger(ret.majorNumber)) {
                 return null;
@@ -115,25 +132,31 @@
         return ret;
     }
 
+    /**
+     * Compares the channel numbers.
+     * <p>
+     * Note that all the channel number arguments should be normalized by
+     * {@link Channel#normalizeDisplayNumber}. The channels retrieved from
+     * {@link ChannelDataManager} are already normalized.
+     */
     public static int compare(String lhs, String rhs) {
         ChannelNumber lhsNumber = parseChannelNumber(lhs);
         ChannelNumber rhsNumber = parseChannelNumber(rhs);
+        // Null first
         if (lhsNumber == null && rhsNumber == null) {
-            return 0;
+            return StringUtils.compare(lhs, rhs);
         } else if (lhsNumber == null /* && rhsNumber != null */) {
             return -1;
-        } else if (lhsNumber != null && rhsNumber == null) {
+        } else if (rhsNumber == null) {
             return 1;
         }
         return lhsNumber.compareTo(rhsNumber);
     }
 
-    public static boolean isInteger(String string) {
+    private static boolean isInteger(String string) {
         try {
             Integer.parseInt(string);
-        } catch(NumberFormatException e) {
-            return false;
-        } catch(NullPointerException e) {
+        } catch(NumberFormatException | NullPointerException e) {
             return false;
         }
         return true;
diff --git a/src/com/android/tv/data/InternalDataUtils.java b/src/com/android/tv/data/InternalDataUtils.java
index 6054f08..e33ca18 100644
--- a/src/com/android/tv/data/InternalDataUtils.java
+++ b/src/com/android/tv/data/InternalDataUtils.java
@@ -21,7 +21,7 @@
 import android.util.Log;
 
 import com.android.tv.data.Program.CriticScore;
-import com.android.tv.dvr.RecordedProgram;
+import com.android.tv.dvr.data.RecordedProgram;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
diff --git a/src/com/android/tv/data/PreviewDataManager.java b/src/com/android/tv/data/PreviewDataManager.java
new file mode 100644
index 0000000..01a5852
--- /dev/null
+++ b/src/com/android/tv/data/PreviewDataManager.java
@@ -0,0 +1,636 @@
+/*
+ * Copyright (C) 2017 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.data;
+
+import android.annotation.TargetApi;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.SQLException;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.media.tv.TvContract;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.support.annotation.IntDef;
+import android.support.annotation.MainThread;
+import android.support.media.tv.ChannelLogoUtils;
+import android.support.media.tv.PreviewProgram;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.tv.R;
+import com.android.tv.util.PermissionUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+/**
+ * Class to manage the preview data.
+ */
+@TargetApi(Build.VERSION_CODES.O)
+@MainThread
+public class PreviewDataManager {
+    private static final String TAG = "PreviewDataManager";
+    // STOPSHIP: set it to false.
+    private static final boolean DEBUG = true;
+
+    /**
+     * Invalid preview channel ID.
+     */
+    public static final long INVALID_PREVIEW_CHANNEL_ID = -1;
+    @IntDef({TYPE_DEFAULT_PREVIEW_CHANNEL, TYPE_RECORDED_PROGRAM_PREVIEW_CHANNEL})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PreviewChannelType{}
+
+    /**
+     * Type of default preview channel
+     */
+    public static final long TYPE_DEFAULT_PREVIEW_CHANNEL = 1;
+    /**
+     * Type of recorded program channel
+     */
+    public static final long TYPE_RECORDED_PROGRAM_PREVIEW_CHANNEL = 2;
+
+    private final Context mContext;
+    private final ContentResolver mContentResolver;
+    private boolean mLoadFinished;
+    private PreviewData mPreviewData = new PreviewData();
+    private final Set<PreviewDataListener> mPreviewDataListeners = new CopyOnWriteArraySet<>();
+
+    private QueryPreviewDataTask mQueryPreviewTask;
+    private final Map<Long, CreatePreviewChannelTask> mCreatePreviewChannelTasks =
+            new HashMap<>();
+    private final Map<Long, UpdatePreviewProgramTask> mUpdatePreviewProgramTasks = new HashMap<>();
+
+    private final int mPreviewChannelLogoWidth;
+    private final int mPreviewChannelLogoHeight;
+
+    public PreviewDataManager(Context context) {
+        mContext = context.getApplicationContext();
+        mContentResolver = context.getContentResolver();
+        mPreviewChannelLogoWidth = mContext.getResources().getDimensionPixelSize(
+                R.dimen.preview_channel_logo_width);
+        mPreviewChannelLogoHeight = mContext.getResources().getDimensionPixelSize(
+                R.dimen.preview_channel_logo_height);
+    }
+
+    /**
+     * Starts the preview data manager.
+     */
+    public void start() {
+        if (mQueryPreviewTask == null) {
+            mQueryPreviewTask = new QueryPreviewDataTask();
+            mQueryPreviewTask.execute();
+        }
+    }
+
+    /**
+     * Stops the preview data manager.
+     */
+    public void stop() {
+        if (mQueryPreviewTask != null) {
+            mQueryPreviewTask.cancel(true);
+        }
+        for (CreatePreviewChannelTask createPreviewChannelTask
+                : mCreatePreviewChannelTasks.values()) {
+            createPreviewChannelTask.cancel(true);
+        }
+        for (UpdatePreviewProgramTask updatePreviewProgramTask
+                : mUpdatePreviewProgramTasks.values()) {
+            updatePreviewProgramTask.cancel(true);
+        }
+
+        mQueryPreviewTask = null;
+        mCreatePreviewChannelTasks.clear();
+        mUpdatePreviewProgramTasks.clear();
+    }
+
+    /**
+     * Gets preview channel ID from the preview channel type.
+     */
+    public @PreviewChannelType long getPreviewChannelId(long previewChannelType) {
+        return mPreviewData.getPreviewChannelId(previewChannelType);
+    }
+
+    /**
+     * Creates default preview channel.
+     */
+    public void createDefaultPreviewChannel(
+            OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener) {
+        createPreviewChannel(TYPE_DEFAULT_PREVIEW_CHANNEL, onPreviewChannelCreationResultListener);
+    }
+
+    /**
+     * Creates a preview channel for specific channel type.
+     */
+    public void createPreviewChannel(@PreviewChannelType long previewChannelType,
+            OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener) {
+        CreatePreviewChannelTask currentRunningCreateTask =
+                mCreatePreviewChannelTasks.get(previewChannelType);
+        if (currentRunningCreateTask == null) {
+            CreatePreviewChannelTask createPreviewChannelTask = new CreatePreviewChannelTask(
+                    previewChannelType);
+            createPreviewChannelTask.addOnPreviewChannelCreationResultListener(
+                    onPreviewChannelCreationResultListener);
+            createPreviewChannelTask.execute();
+            mCreatePreviewChannelTasks.put(previewChannelType, createPreviewChannelTask);
+        } else {
+            currentRunningCreateTask.addOnPreviewChannelCreationResultListener(
+                    onPreviewChannelCreationResultListener);
+        }
+    }
+
+    /**
+     * Returns {@code true} if the preview data is loaded.
+     */
+    public boolean isLoadFinished() {
+        return mLoadFinished;
+    }
+
+    /**
+     * Adds listener.
+     */
+    public void addListener(PreviewDataListener previewDataListener) {
+        mPreviewDataListeners.add(previewDataListener);
+    }
+
+    /**
+     * Removes listener.
+     */
+    public void removeListener(PreviewDataListener previewDataListener) {
+        mPreviewDataListeners.remove(previewDataListener);
+    }
+
+    /**
+     * Updates the preview programs table for a specific preview channel.
+     */
+    public void updatePreviewProgramsForChannel(long previewChannelId,
+            Set<PreviewProgramContent> programs, PreviewDataListener previewDataListener) {
+        UpdatePreviewProgramTask currentRunningUpdateTask =
+                mUpdatePreviewProgramTasks.get(previewChannelId);
+        if (currentRunningUpdateTask != null
+                && currentRunningUpdateTask.getPrograms().equals(programs)) {
+            currentRunningUpdateTask.addPreviewDataListener(previewDataListener);
+            return;
+        }
+        UpdatePreviewProgramTask updatePreviewProgramTask =
+                new UpdatePreviewProgramTask(previewChannelId, programs);
+        updatePreviewProgramTask.addPreviewDataListener(previewDataListener);
+        if (currentRunningUpdateTask != null) {
+            currentRunningUpdateTask.cancel(true);
+            currentRunningUpdateTask.saveStatus();
+            updatePreviewProgramTask.addPreviewDataListeners(
+                    currentRunningUpdateTask.getPreviewDataListeners());
+        }
+        updatePreviewProgramTask.execute();
+        mUpdatePreviewProgramTasks.put(previewChannelId, updatePreviewProgramTask);
+    }
+
+    private void notifyPreviewDataLoadFinished() {
+        for (PreviewDataListener l : mPreviewDataListeners) {
+            l.onPreviewDataLoadFinished();
+        }
+    }
+
+    public interface PreviewDataListener {
+        /**
+         * Called when the preview data is loaded.
+         */
+        void onPreviewDataLoadFinished();
+
+        /**
+         * Called when the preview data is updated.
+         */
+        void onPreviewDataUpdateFinished();
+    }
+
+    public interface OnPreviewChannelCreationResultListener {
+        /**
+         * Called when the creation of preview channel is finished.
+         * @param createdPreviewChannelId The preview channel ID if created successfully,
+         *        otherwise it's {@value #INVALID_PREVIEW_CHANNEL_ID}.
+         */
+        void onPreviewChannelCreationResult(long createdPreviewChannelId);
+    }
+
+    private final class QueryPreviewDataTask extends AsyncTask<Void, Void, PreviewData> {
+        private final String PARAM_PREVIEW = "preview";
+        private final String mChannelSelection = TvContract.Channels.COLUMN_PACKAGE_NAME + "=?";
+
+        @Override
+        protected PreviewData doInBackground(Void... voids) {
+            // Query preview channels and programs.
+            if (DEBUG) Log.d(TAG, "QueryPreviewDataTask.doInBackground");
+            PreviewData previewData = new PreviewData();
+            try {
+                Uri previewChannelsUri =
+                        PreviewDataUtils.addQueryParamToUri(
+                                TvContract.Channels.CONTENT_URI,
+                                new Pair<>(PARAM_PREVIEW, String.valueOf(true)));
+                String packageName = mContext.getPackageName();
+                if (PermissionUtils.hasAccessAllEpg(mContext)) {
+                    try (Cursor cursor =
+                            mContentResolver.query(
+                                    previewChannelsUri,
+                                    android.support.media.tv.Channel.PROJECTION,
+                                    mChannelSelection,
+                                    new String[] {packageName},
+                                    null)) {
+                        if (cursor != null) {
+                            while (cursor.moveToNext()) {
+                                android.support.media.tv.Channel previewChannel =
+                                        android.support.media.tv.Channel.fromCursor(cursor);
+                                Long previewChannelType = previewChannel.getInternalProviderFlag1();
+                                if (previewChannelType != null) {
+                                    previewData.addPreviewChannelId(
+                                            previewChannelType, previewChannel.getId());
+                                }
+                            }
+                        }
+                    }
+                } else {
+                    try (Cursor cursor =
+                            mContentResolver.query(
+                                    previewChannelsUri,
+                                    android.support.media.tv.Channel.PROJECTION,
+                                    null,
+                                    null,
+                                    null)) {
+                        if (cursor != null) {
+                            while (cursor.moveToNext()) {
+                                android.support.media.tv.Channel previewChannel =
+                                        android.support.media.tv.Channel.fromCursor(cursor);
+                                Long previewChannelType = previewChannel.getInternalProviderFlag1();
+                                if (previewChannel.getPackageName() == packageName
+                                        && previewChannelType != null) {
+                                    previewData.addPreviewChannelId(
+                                            previewChannelType, previewChannel.getId());
+                                }
+                            }
+                        }
+                    }
+                }
+
+                for (long previewChannelId : previewData.getAllPreviewChannelIds().values()) {
+                    Uri previewProgramsUriForPreviewChannel =
+                            TvContract.buildPreviewProgramsUriForChannel(previewChannelId);
+                    try (Cursor previewProgramCursor =
+                            mContentResolver.query(
+                                    previewProgramsUriForPreviewChannel,
+                                    PreviewProgram.PROJECTION,
+                                    null,
+                                    null,
+                                    null)) {
+                        if (previewProgramCursor != null) {
+                            while (previewProgramCursor.moveToNext()) {
+                                PreviewProgram previewProgram =
+                                        PreviewProgram.fromCursor(previewProgramCursor);
+                                previewData.addPreviewProgram(previewProgram);
+                            }
+                        }
+                    }
+                }
+            } catch (SQLException e) {
+                Log.w(TAG, "Unable to get preview data", e);
+            }
+            return previewData;
+        }
+
+        @Override
+        protected void onPostExecute(PreviewData result) {
+            super.onPostExecute(result);
+            if (mQueryPreviewTask == this) {
+                mQueryPreviewTask = null;
+                mPreviewData = new PreviewData(result);
+                mLoadFinished = true;
+                notifyPreviewDataLoadFinished();
+            }
+        }
+    }
+
+    private final class CreatePreviewChannelTask extends AsyncTask<Void, Void, Long> {
+        private final long mPreviewChannelType;
+        private Set<OnPreviewChannelCreationResultListener>
+                mOnPreviewChannelCreationResultListeners = new CopyOnWriteArraySet<>();
+
+        public CreatePreviewChannelTask(long previewChannelType) {
+            mPreviewChannelType = previewChannelType;
+        }
+
+        public void addOnPreviewChannelCreationResultListener(
+                OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener) {
+            if (onPreviewChannelCreationResultListener != null) {
+                mOnPreviewChannelCreationResultListeners.add(
+                        onPreviewChannelCreationResultListener);
+            }
+        }
+
+        @Override
+        protected Long doInBackground(Void... params) {
+            if (DEBUG) Log.d(TAG, "CreatePreviewChannelTask.doInBackground");
+            long previewChannelId;
+            try {
+                Uri channelUri = mContentResolver.insert(TvContract.Channels.CONTENT_URI,
+                        PreviewDataUtils.createPreviewChannel(mContext, mPreviewChannelType)
+                                .toContentValues());
+                if (channelUri != null) {
+                    previewChannelId = ContentUris.parseId(channelUri);
+                } else {
+                    Log.e(TAG, "Fail to insert preview channel");
+                    return INVALID_PREVIEW_CHANNEL_ID;
+                }
+            } catch (UnsupportedOperationException | NumberFormatException e) {
+                Log.e(TAG, "Fail to get channel ID");
+                return INVALID_PREVIEW_CHANNEL_ID;
+            }
+            Drawable appIcon = mContext.getApplicationInfo().loadIcon(mContext.getPackageManager());
+            if (appIcon != null && appIcon instanceof BitmapDrawable) {
+                ChannelLogoUtils.storeChannelLogo(mContext, previewChannelId,
+                        Bitmap.createScaledBitmap(((BitmapDrawable) appIcon).getBitmap(),
+                                mPreviewChannelLogoWidth, mPreviewChannelLogoHeight, false));
+            }
+            return previewChannelId;
+        }
+
+        @Override
+        protected void onPostExecute(Long result) {
+            super.onPostExecute(result);
+            if (result != INVALID_PREVIEW_CHANNEL_ID) {
+                mPreviewData.addPreviewChannelId(mPreviewChannelType, result);
+            }
+            for (OnPreviewChannelCreationResultListener onPreviewChannelCreationResultListener
+                    : mOnPreviewChannelCreationResultListeners) {
+                onPreviewChannelCreationResultListener.onPreviewChannelCreationResult(result);
+            }
+            mCreatePreviewChannelTasks.remove(mPreviewChannelType);
+        }
+    }
+
+    /**
+     * Updates the whole data which belongs to the package in preview programs table for a
+     * specific preview channel with a set of {@link PreviewProgramContent}.
+     */
+    private final class UpdatePreviewProgramTask extends AsyncTask<Void, Void, Void> {
+        private long mPreviewChannelId;
+        private Set<PreviewProgramContent> mPrograms;
+        private Map<Long, Long> mCurrentProgramId2PreviewProgramId;
+        private Set<PreviewDataListener> mPreviewDataListeners = new CopyOnWriteArraySet<>();
+
+        public UpdatePreviewProgramTask(long previewChannelId,
+                Set<PreviewProgramContent> programs) {
+            mPreviewChannelId = previewChannelId;
+            mPrograms = programs;
+            if (mPreviewData.getPreviewProgramIds(previewChannelId) == null) {
+                mCurrentProgramId2PreviewProgramId = new HashMap<>();
+            } else {
+                mCurrentProgramId2PreviewProgramId = new HashMap<>(
+                        mPreviewData.getPreviewProgramIds(previewChannelId));
+            }
+        }
+
+        public void addPreviewDataListener(PreviewDataListener previewDataListener) {
+            if (previewDataListener != null) {
+                mPreviewDataListeners.add(previewDataListener);
+            }
+        }
+
+        public void addPreviewDataListeners(Set<PreviewDataListener> previewDataListeners) {
+            if (previewDataListeners != null) {
+                mPreviewDataListeners.addAll(previewDataListeners);
+            }
+        }
+
+        public Set<PreviewProgramContent> getPrograms() {
+            return mPrograms;
+        }
+
+        public Set<PreviewDataListener> getPreviewDataListeners() {
+            return mPreviewDataListeners;
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            if (DEBUG) Log.d(TAG, "UpdatePreviewProgamTask.doInBackground");
+            Map<Long, Long> uncheckedPrograms = new HashMap<>(mCurrentProgramId2PreviewProgramId);
+            for (PreviewProgramContent program : mPrograms) {
+                if (isCancelled()) {
+                    return null;
+                }
+                Long existingPreviewProgramId = uncheckedPrograms.remove(program.getId());
+                if (existingPreviewProgramId != null) {
+                    if (DEBUG) Log.d(TAG, "Preview program " + existingPreviewProgramId + " " +
+                            "already exists for program " + program.getId());
+                    continue;
+                }
+                try {
+                    Uri programUri = mContentResolver.insert(TvContract.PreviewPrograms.CONTENT_URI,
+                            PreviewDataUtils.createPreviewProgramFromContent(program)
+                                    .toContentValues());
+                    if (programUri != null) {
+                        long previewProgramId = ContentUris.parseId(programUri);
+                        mCurrentProgramId2PreviewProgramId.put(program.getId(), previewProgramId);
+                        if (DEBUG) Log.d(TAG, "Add new preview program " + previewProgramId);
+                    } else {
+                        Log.e(TAG, "Fail to insert preview program");
+                    }
+                } catch (Exception e) {
+                    Log.e(TAG, "Fail to get preview program ID");
+                }
+            }
+
+            for (Long key : uncheckedPrograms.keySet()) {
+                if (isCancelled()) {
+                    return null;
+                }
+                try {
+                    if (DEBUG) Log.d(TAG, "Remove preview program " + uncheckedPrograms.get(key));
+                    mContentResolver.delete(TvContract.buildPreviewProgramUri(
+                            uncheckedPrograms.get(key)), null, null);
+                    mCurrentProgramId2PreviewProgramId.remove(key);
+                } catch (Exception e) {
+                    Log.e(TAG, "Fail to remove preview program " + uncheckedPrograms.get(key));
+                }
+            }
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            super.onPostExecute(result);
+            mPreviewData.setPreviewProgramIds(
+                    mPreviewChannelId, mCurrentProgramId2PreviewProgramId);
+            mUpdatePreviewProgramTasks.remove(mPreviewChannelId);
+            for (PreviewDataListener previewDataListener : mPreviewDataListeners) {
+                previewDataListener.onPreviewDataUpdateFinished();
+            }
+        }
+
+        public void saveStatus() {
+            mPreviewData.setPreviewProgramIds(
+                    mPreviewChannelId, mCurrentProgramId2PreviewProgramId);
+        }
+    }
+
+    /**
+     * Class to store the query result of preview data.
+     */
+    private static final class PreviewData {
+        private Map<Long, Long> mPreviewChannelType2Id = new HashMap<>();
+        private Map<Long, Map<Long, Long>> mProgramId2PreviewProgramId = new HashMap<>();
+
+        PreviewData() {
+            mPreviewChannelType2Id = new HashMap<>();
+            mProgramId2PreviewProgramId = new HashMap<>();
+        }
+
+        PreviewData(PreviewData previewData) {
+            mPreviewChannelType2Id = new HashMap<>(previewData.mPreviewChannelType2Id);
+            mProgramId2PreviewProgramId = new HashMap<>(previewData.mProgramId2PreviewProgramId);
+        }
+
+        public void addPreviewProgram(PreviewProgram previewProgram) {
+            long previewChannelId = previewProgram.getChannelId();
+            Map<Long, Long> programId2PreviewProgram =
+                    mProgramId2PreviewProgramId.get(previewChannelId);
+            if (programId2PreviewProgram == null) {
+                programId2PreviewProgram = new HashMap<>();
+            }
+            mProgramId2PreviewProgramId.put(previewChannelId, programId2PreviewProgram);
+            if (previewProgram.getInternalProviderId() != null) {
+                programId2PreviewProgram.put(
+                        Long.parseLong(previewProgram.getInternalProviderId()),
+                        previewProgram.getId());
+            }
+        }
+
+        public @PreviewChannelType long getPreviewChannelId(long previewChannelType) {
+            Long result = mPreviewChannelType2Id.get(previewChannelType);
+            return result == null ? INVALID_PREVIEW_CHANNEL_ID : result;
+        }
+
+        public Map<Long, Long> getAllPreviewChannelIds() {
+            return mPreviewChannelType2Id;
+        }
+
+        public void addPreviewChannelId(long previewChannelType, long previewChannelId) {
+            mPreviewChannelType2Id.put(previewChannelType, previewChannelId);
+        }
+
+        public void removePreviewChannelId(long previewChannelType) {
+            mPreviewChannelType2Id.remove(previewChannelType);
+        }
+
+        public void removePreviewChannel(long previewChannelId) {
+            removePreviewChannelId(previewChannelId);
+            removePreviewProgramIds(previewChannelId);
+        }
+
+        public Map<Long, Long> getPreviewProgramIds(long previewChannelId) {
+            return mProgramId2PreviewProgramId.get(previewChannelId);
+        }
+
+        public Map<Long, Map<Long, Long>> getAllPreviewProgramIds() {
+            return mProgramId2PreviewProgramId;
+        }
+
+        public void setPreviewProgramIds(
+                long previewChannelId, Map<Long, Long> programId2PreviewProgramId) {
+            mProgramId2PreviewProgramId.put(previewChannelId, programId2PreviewProgramId);
+        }
+
+        public void removePreviewProgramIds(long previewChannelId) {
+            mProgramId2PreviewProgramId.remove(previewChannelId);
+        }
+    }
+
+    /**
+     * A utils class for preview data.
+     */
+    public final static class PreviewDataUtils {
+        /**
+         * Creates a preview channel.
+         */
+        public static android.support.media.tv.Channel createPreviewChannel(
+                Context context, @PreviewChannelType long previewChannelType) {
+            if (previewChannelType == TYPE_RECORDED_PROGRAM_PREVIEW_CHANNEL) {
+                return createRecordedProgramPreviewChannel(context, previewChannelType);
+            }
+            return createDefaultPreviewChannel(context, previewChannelType);
+        }
+
+        private static android.support.media.tv.Channel createDefaultPreviewChannel(
+                Context context, @PreviewChannelType long previewChannelType) {
+            android.support.media.tv.Channel.Builder builder =
+                    new android.support.media.tv.Channel.Builder();
+            CharSequence appLabel =
+                    context.getApplicationInfo().loadLabel(context.getPackageManager());
+            CharSequence appDescription =
+                    context.getApplicationInfo().loadDescription(context.getPackageManager());
+            builder.setType(TvContract.Channels.TYPE_PREVIEW)
+                    .setDisplayName(appLabel == null ? null : appLabel.toString())
+                    .setDescription(appDescription == null ?  null : appDescription.toString())
+                    .setAppLinkIntentUri(TvContract.Channels.CONTENT_URI)
+                    .setInternalProviderFlag1(previewChannelType);
+            return builder.build();
+        }
+
+        private static android.support.media.tv.Channel createRecordedProgramPreviewChannel(
+                Context context, @PreviewChannelType long previewChannelType) {
+            android.support.media.tv.Channel.Builder builder =
+                    new android.support.media.tv.Channel.Builder();
+            builder.setType(TvContract.Channels.TYPE_PREVIEW)
+                    .setDisplayName(context.getResources().getString(
+                            R.string.recorded_programs_preview_channel))
+                    .setAppLinkIntentUri(TvContract.Channels.CONTENT_URI)
+                    .setInternalProviderFlag1(previewChannelType);
+            return builder.build();
+        }
+
+        /**
+         * Creates a preview program.
+         */
+        public static PreviewProgram createPreviewProgramFromContent(
+                PreviewProgramContent program) {
+            PreviewProgram.Builder builder = new PreviewProgram.Builder();
+            builder.setChannelId(program.getPreviewChannelId())
+                    .setType(program.getType())
+                    .setLive(program.getLive())
+                    .setTitle(program.getTitle())
+                    .setDescription(program.getDescription())
+                    .setPosterArtUri(program.getPosterArtUri())
+                    .setIntentUri(program.getIntentUri())
+                    .setPreviewVideoUri(program.getPreviewVideoUri())
+                    .setInternalProviderId(Long.toString(program.getId()));
+            return builder.build();
+        }
+
+        /**
+         * Appends query parameters to a Uri.
+         */
+        public static Uri addQueryParamToUri(Uri uri, Pair<String, String> param) {
+            return uri.buildUpon().appendQueryParameter(param.first, param.second).build();
+        }
+    }
+}
diff --git a/src/com/android/tv/data/PreviewProgramContent.java b/src/com/android/tv/data/PreviewProgramContent.java
new file mode 100644
index 0000000..39f5051
--- /dev/null
+++ b/src/com/android/tv/data/PreviewProgramContent.java
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2017 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.data;
+
+import android.content.Context;
+import android.media.tv.TvContract;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import com.android.tv.TvApplication;
+import com.android.tv.dvr.data.RecordedProgram;
+
+import java.util.Objects;
+
+/**
+ * A class to store the content of preview programs.
+ */
+public class PreviewProgramContent {
+    private final static String PARAM_INPUT = "input";
+
+    private long mId;
+    private long mPreviewChannelId;
+    private int mType;
+    private boolean mLive;
+    private String mTitle;
+    private String mDescription;
+    private Uri mPosterArtUri;
+    private Uri mIntentUri;
+    private Uri mPreviewVideoUri;
+
+    /**
+     * Create preview program content from {@link Program}
+     */
+    public static PreviewProgramContent createFromProgram(Context context,
+            long previewChannelId, Program program) {
+        Channel channel = TvApplication.getSingletons(context).getChannelDataManager()
+                .getChannel(program.getChannelId());
+        if (channel == null) {
+            return null;
+        }
+        String channelDisplayName = channel.getDisplayName();
+        return new PreviewProgramContent.Builder()
+                .setId(program.getId())
+                .setPreviewChannelId(previewChannelId)
+                .setType(TvContract.PreviewPrograms.TYPE_CHANNEL)
+                .setLive(true)
+                .setTitle(program.getTitle())
+                .setDescription(!TextUtils.isEmpty(channelDisplayName)
+                        ? channelDisplayName : channel.getDisplayNumber())
+                .setPosterArtUri(Uri.parse(program.getPosterArtUri()))
+                .setIntentUri(channel.getUri())
+                .setPreviewVideoUri(PreviewDataManager.PreviewDataUtils.addQueryParamToUri(
+                        channel.getUri(), new Pair<>(PARAM_INPUT, channel.getInputId())))
+                .build();
+    }
+
+    /**
+     * Create preview program content from {@link RecordedProgram}
+     */
+    public static PreviewProgramContent createFromRecordedProgram(
+            Context context, long previewChannelId, RecordedProgram recordedProgram) {
+        Channel channel = TvApplication.getSingletons(context).getChannelDataManager()
+                .getChannel(recordedProgram.getChannelId());
+        String channelDisplayName = null;
+        if (channel != null) {
+            channelDisplayName = channel.getDisplayName();
+        }
+        Uri recordedProgramUri = TvContract.buildRecordedProgramUri(recordedProgram.getId());
+        return new PreviewProgramContent.Builder()
+                .setId(recordedProgram.getId())
+                .setPreviewChannelId(previewChannelId)
+                .setType(TvContract.PreviewPrograms.TYPE_CLIP)
+                .setTitle(recordedProgram.getTitle())
+                .setDescription(channelDisplayName != null ? channelDisplayName : "")
+                .setPosterArtUri(Uri.parse(recordedProgram.getPosterArtUri()))
+                .setIntentUri(recordedProgramUri)
+                .setPreviewVideoUri(PreviewDataManager.PreviewDataUtils.addQueryParamToUri(
+                        recordedProgramUri, new Pair<>(PARAM_INPUT, recordedProgram.getInputId())))
+                .build();
+    }
+
+    private PreviewProgramContent() { }
+
+    public void copyFrom(PreviewProgramContent other) {
+        if (this == other) {
+            return;
+        }
+        mId = other.mId;
+        mPreviewChannelId = other.mPreviewChannelId;
+        mType = other.mType;
+        mLive = other.mLive;
+        mTitle = other.mTitle;
+        mDescription = other.mDescription;
+        mPosterArtUri = other.mPosterArtUri;
+        mIntentUri = other.mIntentUri;
+        mPreviewVideoUri = other.mPreviewVideoUri;
+    }
+
+    /**
+     * Returns the id, which is an identification. It usually comes from the original data which
+     * create the {@PreviewProgramContent}.
+     */
+    public long getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the preview channel id which the preview program belongs to.
+     */
+    public long getPreviewChannelId() {
+        return mPreviewChannelId;
+    }
+
+    /**
+     * Returns the type of the preview program.
+     */
+    public int getType() {
+        return mType;
+    }
+
+    /**
+     * Returns whether the preview program is live or not.
+     */
+    public boolean getLive() {
+        return mLive;
+    }
+
+    /**
+     * Returns the title of the preview program.
+     */
+    public String getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Returns the description of the preview program.
+     */
+    public String getDescription() {
+        return mDescription;
+    }
+
+    /**
+     * Returns the poster art uri of the preview program.
+     */
+    public Uri getPosterArtUri() {
+        return mPosterArtUri;
+    }
+
+    /**
+     * Returns the intent uri of the preview program.
+     */
+    public Uri getIntentUri() {
+        return mIntentUri;
+    }
+
+    /**
+     * Returns the preview video uri of the preview program.
+     */
+    public Uri getPreviewVideoUri() {
+        return mPreviewVideoUri;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof PreviewProgramContent)) {
+            return false;
+        }
+        PreviewProgramContent previewProgramContent = (PreviewProgramContent) other;
+        return previewProgramContent.mId == mId
+                && previewProgramContent.mPreviewChannelId == mPreviewChannelId
+                && previewProgramContent.mType == mType
+                && previewProgramContent.mLive == mLive
+                && Objects.equals(previewProgramContent.mTitle, mTitle)
+                && Objects.equals(previewProgramContent.mDescription, mDescription)
+                && Objects.equals(previewProgramContent.mPosterArtUri, mPosterArtUri)
+                && Objects.equals(previewProgramContent.mIntentUri, mIntentUri)
+                && Objects.equals(previewProgramContent.mPreviewVideoUri, mPreviewVideoUri);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mId, mPreviewChannelId, mType, mLive, mTitle, mDescription,
+                mPosterArtUri, mIntentUri, mPreviewVideoUri);
+    }
+
+    public static final class Builder {
+        private final PreviewProgramContent mPreviewProgramContent;
+
+        public Builder() {
+            mPreviewProgramContent = new PreviewProgramContent();
+        }
+
+        public Builder setId(long id) {
+            mPreviewProgramContent.mId = id;
+            return this;
+        }
+
+        public Builder setPreviewChannelId(long previewChannelId) {
+            mPreviewProgramContent.mPreviewChannelId = previewChannelId;
+            return this;
+        }
+
+        public Builder setType(int type) {
+            mPreviewProgramContent.mType = type;
+            return this;
+        }
+
+        public Builder setLive(boolean live) {
+            mPreviewProgramContent.mLive = live;
+            return this;
+        }
+
+        public Builder setTitle(String title) {
+            mPreviewProgramContent.mTitle = title;
+            return this;
+        }
+
+        public Builder setDescription(String description) {
+            mPreviewProgramContent.mDescription = description;
+            return this;
+        }
+
+        public Builder setPosterArtUri(Uri posterArtUri) {
+            mPreviewProgramContent.mPosterArtUri = posterArtUri;
+            return this;
+        }
+
+        public Builder setIntentUri(Uri intentUri) {
+            mPreviewProgramContent.mIntentUri = intentUri;
+            return this;
+        }
+
+        public Builder setPreviewVideoUri(Uri previewVideoUri) {
+            mPreviewProgramContent.mPreviewVideoUri = previewVideoUri;
+            return this;
+        }
+
+        public PreviewProgramContent build() {
+            PreviewProgramContent previewProgramContent = new PreviewProgramContent();
+            previewProgramContent.copyFrom(mPreviewProgramContent);
+            return previewProgramContent;
+        }
+    }
+}
diff --git a/src/com/android/tv/data/Program.java b/src/com/android/tv/data/Program.java
index b9cd3d8..071c702 100644
--- a/src/com/android/tv/data/Program.java
+++ b/src/com/android/tv/data/Program.java
@@ -16,21 +16,23 @@
 
 package com.android.tv.data;
 
+import android.annotation.SuppressLint;
+import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
 import android.media.tv.TvContentRating;
 import android.media.tv.TvContract;
+import android.media.tv.TvContract.Programs;
+import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.support.annotation.VisibleForTesting;
-import android.support.v4.os.BuildCompat;
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.tv.R;
 import com.android.tv.common.BuildConfig;
 import com.android.tv.common.CollectionUtils;
 import com.android.tv.common.TvContentRatingCache;
@@ -88,9 +90,11 @@
     public static final String[] PROJECTION = createProjection();
 
     private static String[] createProjection() {
-        return CollectionUtils
-                .concatAll(PROJECTION_BASE, BuildCompat.isAtLeastN() ? PROJECTION_ADDED_IN_NYC
-                : PROJECTION_DEPRECATED_IN_NYC);
+        return CollectionUtils.concatAll(
+                PROJECTION_BASE,
+                Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+                        ? PROJECTION_ADDED_IN_NYC
+                        : PROJECTION_DEPRECATED_IN_NYC);
     }
 
     /**
@@ -135,7 +139,7 @@
             InternalDataUtils.deserializeInternalProviderData(cursor.getBlob(index), builder);
         }
         index++;
-        if (BuildCompat.isAtLeastN()) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             builder.setSeasonNumber(cursor.getString(index++));
             builder.setSeasonTitle(cursor.getString(index++));
             builder.setEpisodeNumber(cursor.getString(index++));
@@ -213,11 +217,6 @@
     private TvContentRating[] mContentRatings;
     private boolean mRecordingProhibited;
 
-    /**
-     * TODO(DVR): Need to fill the following data.
-     */
-    private boolean mRecordingScheduled;
-
     private Program() {
         // Do nothing.
     }
@@ -268,45 +267,11 @@
     /**
      * Returns the episode title.
      */
+    @Override
     public String getEpisodeTitle() {
         return mEpisodeTitle;
     }
 
-    /**
-     * Returns season number, episode number and episode title for display.
-     */
-    @Override
-    public String getEpisodeDisplayTitle(Context context) {
-        if (!TextUtils.isEmpty(mEpisodeNumber)) {
-            String episodeTitle = mEpisodeTitle == null ? "" : mEpisodeTitle;
-            if (TextUtils.equals(mSeasonNumber, "0")) {
-                // Do not show "S0: ".
-                return String.format(context.getResources().getString(
-                        R.string.display_episode_title_format_no_season_number),
-                        mEpisodeNumber, episodeTitle);
-            } else {
-                return String.format(context.getResources().getString(
-                        R.string.display_episode_title_format),
-                        mSeasonNumber, mEpisodeNumber, episodeTitle);
-            }
-        }
-        return mEpisodeTitle;
-    }
-
-    @Override
-    public String getTitleWithEpisodeNumber(Context context) {
-        if (TextUtils.isEmpty(mTitle)) {
-            return mTitle;
-        }
-        if (TextUtils.isEmpty(mSeasonNumber) || mSeasonNumber.equals("0")) {
-            return TextUtils.isEmpty(mEpisodeNumber) ? mTitle : context.getString(
-                    R.string.program_title_with_episode_number_no_season, mTitle, mEpisodeNumber);
-        } else {
-            return context.getString(R.string.program_title_with_episode_number, mTitle,
-                    mSeasonNumber, mEpisodeNumber);
-        }
-    }
-
     @Override
     public String getSeasonNumber() {
         return mSeasonNumber;
@@ -361,6 +326,8 @@
         return mCriticScores;
     }
 
+    @Nullable
+    @Override
     public TvContentRating[] getContentRatings() {
         return mContentRatings;
     }
@@ -495,6 +462,63 @@
         return builder.append("}").toString();
     }
 
+    /**
+     * Translates a {@link Program} to {@link ContentValues} that are ready to be written into
+     * Database.
+     */
+    @SuppressLint("InlinedApi")
+    @SuppressWarnings("deprecation")
+    public static ContentValues toContentValues(Program program) {
+        ContentValues values = new ContentValues();
+        values.put(TvContract.Programs.COLUMN_CHANNEL_ID, program.getChannelId());
+        putValue(values, TvContract.Programs.COLUMN_TITLE, program.getTitle());
+        putValue(values, TvContract.Programs.COLUMN_EPISODE_TITLE, program.getEpisodeTitle());
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            putValue(values, TvContract.Programs.COLUMN_SEASON_DISPLAY_NUMBER,
+                    program.getSeasonNumber());
+            putValue(values, TvContract.Programs.COLUMN_EPISODE_DISPLAY_NUMBER,
+                    program.getEpisodeNumber());
+        } else {
+            putValue(values, TvContract.Programs.COLUMN_SEASON_NUMBER, program.getSeasonNumber());
+            putValue(values, TvContract.Programs.COLUMN_EPISODE_NUMBER, program.getEpisodeNumber());
+        }
+        putValue(values, TvContract.Programs.COLUMN_SHORT_DESCRIPTION, program.getDescription());
+        putValue(values, TvContract.Programs.COLUMN_LONG_DESCRIPTION, program.getLongDescription());
+        putValue(values, TvContract.Programs.COLUMN_POSTER_ART_URI, program.getPosterArtUri());
+        putValue(values, TvContract.Programs.COLUMN_THUMBNAIL_URI, program.getThumbnailUri());
+        String[] canonicalGenres = program.getCanonicalGenres();
+        if (canonicalGenres != null && canonicalGenres.length > 0) {
+            putValue(values, TvContract.Programs.COLUMN_CANONICAL_GENRE,
+                    TvContract.Programs.Genres.encode(canonicalGenres));
+        } else {
+            putValue(values, TvContract.Programs.COLUMN_CANONICAL_GENRE, "");
+        }
+        putValue(values, Programs.COLUMN_CONTENT_RATING,
+                TvContentRatingCache.contentRatingsToString(program.getContentRatings()));
+        values.put(TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS,
+                program.getStartTimeUtcMillis());
+        values.put(TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, program.getEndTimeUtcMillis());
+        putValue(values, TvContract.Programs.COLUMN_INTERNAL_PROVIDER_DATA,
+                InternalDataUtils.serializeInternalProviderData(program));
+        return values;
+    }
+
+    private static void putValue(ContentValues contentValues, String key, String value) {
+        if (TextUtils.isEmpty(value)) {
+            contentValues.putNull(key);
+        } else {
+            contentValues.put(key, value);
+        }
+    }
+
+    private static void putValue(ContentValues contentValues, String key, byte[] value) {
+        if (value == null || value.length == 0) {
+            contentValues.putNull(key);
+        } else {
+            contentValues.put(key, value);
+        }
+    }
+
     public void copyFrom(Program other) {
         if (this == other) {
             return;
@@ -524,13 +548,6 @@
     }
 
     /**
-     * Checks whether the program is episodic or not.
-     */
-    public boolean isEpisodic() {
-        return mSeriesId != null;
-    }
-
-    /**
      * A Builder for the Program class
      */
     public static final class Builder {
@@ -799,8 +816,12 @@
          */
         public Program build() {
             // Generate the series ID for the episodic program of other TV input.
-            if (TextUtils.isEmpty(mProgram.mSeriesId)
+            if (TextUtils.isEmpty(mProgram.mTitle)) {
+                // If title is null, series cannot be generated for this program.
+                setSeriesId(null);
+            } else if (TextUtils.isEmpty(mProgram.mSeriesId)
                     && !TextUtils.isEmpty(mProgram.mEpisodeNumber)) {
+                // If series ID is not set, generate it for the episodic program of other TV input.
                 setSeriesId(BaseProgram.generateSeriesId(mProgram.mPackageName, mProgram.mTitle));
             }
             Program program = new Program();
@@ -820,17 +841,20 @@
     }
 
     /**
-     * Loads the program poster art and returns it via {@code callback}.<p>
+     * Loads the program poster art and returns it via {@code callback}.
      * <p>
      * Note that it may directly call {@code callback} if the program poster art already is loaded.
+     *
+     * @return {@code true} if the load is complete and the callback is executed.
      */
     @UiThread
-    public void loadPosterArt(Context context, int posterArtWidth, int posterArtHeight,
+    public boolean loadPosterArt(Context context, int posterArtWidth, int posterArtHeight,
             ImageLoader.ImageLoaderCallback callback) {
         if (mPosterArtUri == null) {
-            return;
+            return false;
         }
-        ImageLoader.loadBitmap(context, mPosterArtUri, posterArtWidth, posterArtHeight, callback);
+        return ImageLoader.loadBitmap(
+                context, mPosterArtUri, posterArtWidth, posterArtHeight, callback);
     }
 
     public static boolean isDuplicate(Program p1, Program p2) {
diff --git a/src/com/android/tv/data/ProgramDataManager.java b/src/com/android/tv/data/ProgramDataManager.java
index d2af33a..8cb5e74 100644
--- a/src/com/android/tv/data/ProgramDataManager.java
+++ b/src/com/android/tv/data/ProgramDataManager.java
@@ -26,6 +26,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.support.annotation.AnyThread;
 import android.support.annotation.MainThread;
 import android.support.annotation.VisibleForTesting;
 import android.util.ArraySet;
@@ -35,8 +36,6 @@
 
 import com.android.tv.common.MemoryManageable;
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.epg.EpgFetcher;
-import com.android.tv.experiments.Experiments;
 import com.android.tv.util.AsyncDbTask;
 import com.android.tv.util.Clock;
 import com.android.tv.util.MultiLongSparseArray;
@@ -51,6 +50,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 
 @MainThread
@@ -85,10 +85,12 @@
     private final Clock mClock;
     private final ContentResolver mContentResolver;
     private boolean mStarted;
+    // Updated only on the main thread.
+    private volatile boolean mCurrentProgramsLoadFinished;
     private ProgramsUpdateTask mProgramsUpdateTask;
     private final LongSparseArray<UpdateCurrentProgramForChannelTask> mProgramUpdateTaskMap =
             new LongSparseArray<>();
-    private final Map<Long, Program> mChannelIdCurrentProgramMap = new HashMap<>();
+    private final Map<Long, Program> mChannelIdCurrentProgramMap = new ConcurrentHashMap<>();
     private final MultiLongSparseArray<OnCurrentProgramUpdatedListener>
             mChannelId2ProgramUpdatedListeners = new MultiLongSparseArray<>();
     private final Handler mHandler;
@@ -109,17 +111,14 @@
 
     private boolean mPauseProgramUpdate = false;
     private final LruCache<Long, Program> mZeroLengthProgramCache = new LruCache<>(10);
-    private final EpgFetcher mEpgFetcher;
 
+    @MainThread
     public ProgramDataManager(Context context) {
-        this(context.getContentResolver(), Clock.SYSTEM, Looper.myLooper(),
-                EpgFetcher.getInstance(context));
+        this(context.getContentResolver(), Clock.SYSTEM, Looper.myLooper());
     }
 
     @VisibleForTesting
-    ProgramDataManager(ContentResolver contentResolver, Clock time, Looper looper,
-            EpgFetcher epgFetcher) {
-        mEpgFetcher = epgFetcher;
+    ProgramDataManager(ContentResolver contentResolver, Clock time, Looper looper) {
         mClock = time;
         mContentResolver = contentResolver;
         mHandler = new MyHandler(looper);
@@ -175,9 +174,6 @@
         }
         mContentResolver.registerContentObserver(Programs.CONTENT_URI,
                 true, mProgramObserver);
-        if (mEpgFetcher != null && Experiments.CLOUD_EPG.get()) {
-            mEpgFetcher.start();
-        }
     }
 
     /**
@@ -190,10 +186,6 @@
             return;
         }
         mStarted = false;
-
-        if (mEpgFetcher != null) {
-            mEpgFetcher.stop();
-        }
         mContentResolver.unregisterContentObserver(mProgramObserver);
         mHandler.removeCallbacksAndMessages(null);
 
@@ -205,13 +197,23 @@
         }
     }
 
-    /**
-     * Returns the current program at the specified channel.
-     */
+    @AnyThread
+    public boolean isCurrentProgramsLoadFinished() {
+        return mCurrentProgramsLoadFinished;
+    }
+
+    /** Returns the current program at the specified channel. */
+    @AnyThread
     public Program getCurrentProgram(long channelId) {
         return mChannelIdCurrentProgramMap.get(channelId);
     }
 
+    /** Returns all the current programs. */
+    @AnyThread
+    public List<Program> getCurrentPrograms() {
+        return new ArrayList<>(mChannelIdCurrentProgramMap.values());
+    }
+
     /**
      * Reloads program data.
      */
@@ -338,19 +340,19 @@
     }
 
     private void notifyCurrentProgramUpdate(long channelId, Program program) {
-
         for (OnCurrentProgramUpdatedListener listener : mChannelId2ProgramUpdatedListeners
                 .get(channelId)) {
             listener.onCurrentProgramUpdated(channelId, program);
-            }
+        }
         for (OnCurrentProgramUpdatedListener listener : mChannelId2ProgramUpdatedListeners
                 .get(Channel.INVALID_ID)) {
             listener.onCurrentProgramUpdated(channelId, program);
-            }
+        }
     }
 
     private void updateCurrentProgram(long channelId, Program program) {
-        Program previousProgram = mChannelIdCurrentProgramMap.put(channelId, program);
+        Program previousProgram = program == null ? mChannelIdCurrentProgramMap.remove(channelId)
+                : mChannelIdCurrentProgramMap.put(channelId, program);
         if (!Objects.equals(program, previousProgram)) {
             if (mPrefetchEnabled) {
                 removePreviousProgramsAndUpdateCurrentProgramInCache(channelId, program);
@@ -581,22 +583,22 @@
         protected void onPostExecute(List<Program> programs) {
             if (DEBUG) Log.d(TAG, "ProgramsUpdateTask done");
             mProgramsUpdateTask = null;
-            if (programs == null) {
-                return;
-            }
-            Set<Long> removedChannelIds = new HashSet<>(mChannelIdCurrentProgramMap.keySet());
-            for (Program program : programs) {
-                long channelId = program.getChannelId();
-                updateCurrentProgram(channelId, program);
-                removedChannelIds.remove(channelId);
-            }
-            for (Long channelId : removedChannelIds) {
-                if (mPrefetchEnabled) {
-                    mChannelIdProgramCache.remove(channelId);
+            if (programs != null) {
+                Set<Long> removedChannelIds = new HashSet<>(mChannelIdCurrentProgramMap.keySet());
+                for (Program program : programs) {
+                    long channelId = program.getChannelId();
+                    updateCurrentProgram(channelId, program);
+                    removedChannelIds.remove(channelId);
                 }
-                mChannelIdCurrentProgramMap.remove(channelId);
-                notifyCurrentProgramUpdate(channelId, null);
+                for (Long channelId : removedChannelIds) {
+                    if (mPrefetchEnabled) {
+                        mChannelIdProgramCache.remove(channelId);
+                    }
+                    mChannelIdCurrentProgramMap.remove(channelId);
+                    notifyCurrentProgramUpdate(channelId, null);
+                }
             }
+            mCurrentProgramsLoadFinished = true;
         }
     }
 
diff --git a/src/com/android/tv/data/StreamInfo.java b/src/com/android/tv/data/StreamInfo.java
index fe461f1..709863c 100644
--- a/src/com/android/tv/data/StreamInfo.java
+++ b/src/com/android/tv/data/StreamInfo.java
@@ -38,5 +38,9 @@
     int getAudioChannelCount();
     boolean hasClosedCaption();
     boolean isVideoAvailable();
+    /**
+     *  Returns true, if video or audio is available.
+     */
+    boolean isVideoOrAudioAvailable();
     int getVideoUnavailableReason();
 }
diff --git a/src/com/android/tv/data/WatchedHistoryManager.java b/src/com/android/tv/data/WatchedHistoryManager.java
index 5931933..3edd7b1 100644
--- a/src/com/android/tv/data/WatchedHistoryManager.java
+++ b/src/com/android/tv/data/WatchedHistoryManager.java
@@ -10,15 +10,14 @@
 import android.support.annotation.MainThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
+import android.support.annotation.WorkerThread;
 import android.util.Log;
 
 import com.android.tv.common.SharedPreferencesUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Scanner;
 import java.util.concurrent.TimeUnit;
@@ -28,15 +27,15 @@
  *
  * <p>When there is no access to watched table of TvProvider,
  * this class is used to build up watched history and to compute recent channels.
+ * <p>Note that this class is not thread safe. Please use this on one thread.
  */
 public class WatchedHistoryManager {
     private final static String TAG = "WatchedHistoryManager";
-    private final boolean DEBUG = false;
+    private final static boolean DEBUG = false;
 
     private static final int MAX_HISTORY_SIZE = 10000;
     private static final String PREF_KEY_LAST_INDEX = "last_index";
     private static final long MIN_DURATION_MS = TimeUnit.SECONDS.toMillis(10);
-    private static final long RECENT_CHANNEL_THRESHOLD_MS = TimeUnit.MINUTES.toMillis(5);
 
     private final List<WatchedRecord> mWatchedHistory = new ArrayList<>();
     private final List<WatchedRecord> mPendingRecords = new ArrayList<>();
@@ -92,11 +91,7 @@
     WatchedHistoryManager(Context context, int maxHistorySize) {
         mContext = context.getApplicationContext();
         mMaxHistorySize = maxHistorySize;
-        if (Looper.myLooper() == null) {
-            mHandler = new Handler(Looper.getMainLooper());
-        } else {
-            mHandler = new Handler();
-        }
+        mHandler = new Handler();
     }
 
     /**
@@ -107,56 +102,70 @@
             return;
         }
         mStarted = true;
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... params) {
-                mSharedPreferences = mContext.getSharedPreferences(
-                        SharedPreferencesUtils.SHARED_PREF_WATCHED_HISTORY, Context.MODE_PRIVATE);
-                mLastIndex = mSharedPreferences.getLong(PREF_KEY_LAST_INDEX, -1);
-                if (mLastIndex >= 0 && mLastIndex < mMaxHistorySize) {
-                    for (int i = 0; i <= mLastIndex; ++i) {
-                        WatchedRecord record =
-                                decode(mSharedPreferences.getString(getSharedPreferencesKey(i),
-                                        null));
-                        if (record != null) {
-                            mWatchedHistory.add(record);
-                        }
-                    }
-                } else if (mLastIndex >= mMaxHistorySize) {
-                    for (long i = mLastIndex - mMaxHistorySize + 1; i <= mLastIndex; ++i) {
-                        WatchedRecord record = decode(mSharedPreferences.getString(
-                                getSharedPreferencesKey(i), null));
-                        if (record != null) {
-                            mWatchedHistory.add(record);
-                        }
-                    }
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    loadWatchedHistory();
+                    return null;
                 }
-                return null;
-            }
 
-            @Override
-            protected void onPostExecute(Void params) {
-                mLoaded = true;
-                if (DEBUG) {
-                    Log.d(TAG, "Loaded: size=" + mWatchedHistory.size() + " index=" + mLastIndex);
+                @Override
+                protected void onPostExecute(Void params) {
+                    onLoadFinished();
                 }
-                if (!mPendingRecords.isEmpty()) {
-                    Editor editor = mSharedPreferences.edit();
-                    for (WatchedRecord record : mPendingRecords) {
-                        mWatchedHistory.add(record);
-                        ++mLastIndex;
-                        editor.putString(getSharedPreferencesKey(mLastIndex), encode(record));
-                    }
-                    editor.putLong(PREF_KEY_LAST_INDEX, mLastIndex).apply();
-                    mPendingRecords.clear();
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        } else {
+            loadWatchedHistory();
+            onLoadFinished();
+        }
+    }
+
+    @WorkerThread
+    private void loadWatchedHistory() {
+        mSharedPreferences = mContext.getSharedPreferences(
+                SharedPreferencesUtils.SHARED_PREF_WATCHED_HISTORY, Context.MODE_PRIVATE);
+        mLastIndex = mSharedPreferences.getLong(PREF_KEY_LAST_INDEX, -1);
+        if (mLastIndex >= 0 && mLastIndex < mMaxHistorySize) {
+            for (int i = 0; i <= mLastIndex; ++i) {
+                WatchedRecord record =
+                        decode(mSharedPreferences.getString(getSharedPreferencesKey(i),
+                                null));
+                if (record != null) {
+                    mWatchedHistory.add(record);
                 }
-                if (mListener != null) {
-                    mListener.onLoadFinished();
-                }
-                mSharedPreferences.registerOnSharedPreferenceChangeListener(
-                        mOnSharedPreferenceChangeListener);
             }
-        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        } else if (mLastIndex >= mMaxHistorySize) {
+            for (long i = mLastIndex - mMaxHistorySize + 1; i <= mLastIndex; ++i) {
+                WatchedRecord record = decode(mSharedPreferences.getString(
+                        getSharedPreferencesKey(i), null));
+                if (record != null) {
+                    mWatchedHistory.add(record);
+                }
+            }
+        }
+    }
+
+    private void onLoadFinished() {
+        mLoaded = true;
+        if (DEBUG) {
+            Log.d(TAG, "Loaded: size=" + mWatchedHistory.size() + " index=" + mLastIndex);
+        }
+        if (!mPendingRecords.isEmpty()) {
+            Editor editor = mSharedPreferences.edit();
+            for (WatchedRecord record : mPendingRecords) {
+                mWatchedHistory.add(record);
+                ++mLastIndex;
+                editor.putString(getSharedPreferencesKey(mLastIndex), encode(record));
+            }
+            editor.putLong(PREF_KEY_LAST_INDEX, mLastIndex).apply();
+            mPendingRecords.clear();
+        }
+        if (mListener != null) {
+            mListener.onLoadFinished();
+        }
+        mSharedPreferences.registerOnSharedPreferenceChangeListener(
+                mOnSharedPreferenceChangeListener);
     }
 
     @VisibleForTesting
@@ -204,52 +213,6 @@
         return Collections.unmodifiableList(mWatchedHistory);
     }
 
-    /**
-     * Returns the list of recently watched channels.
-     */
-    public List<Channel> buildRecentChannel(ChannelDataManager channelDataManager, int maxCount) {
-        List<Channel> list = new ArrayList<>();
-        Map<Long, Long> durationMap = new HashMap<>();
-        for (int i = mWatchedHistory.size() - 1; i >= 0; --i) {
-            WatchedRecord record = mWatchedHistory.get(i);
-            long channelId = record.channelId;
-            Channel channel = channelDataManager.getChannel(channelId);
-            if (channel == null || !channel.isBrowsable()) {
-                continue;
-            }
-            Long duration = durationMap.get(channelId);
-            if (duration == null) {
-                duration = 0L;
-            }
-            if (duration >= RECENT_CHANNEL_THRESHOLD_MS) {
-                continue;
-            }
-            if (list.isEmpty()) {
-                // We put the first recent channel regardless of RECENT_CHANNEL_THREASHOLD.
-                // It has the similar functionality as the previous channel in a usual remote
-                // controller.
-                list.add(channel);
-                durationMap.put(channelId, RECENT_CHANNEL_THRESHOLD_MS);
-            } else {
-                duration += record.duration;
-                durationMap.put(channelId, duration);
-                if (duration >= RECENT_CHANNEL_THRESHOLD_MS) {
-                    list.add(channel);
-                }
-            }
-            if (list.size() >= maxCount) {
-                break;
-            }
-        }
-        if (DEBUG) {
-            Log.d(TAG, "Build recent channel");
-            for (Channel channel : list) {
-                Log.d(TAG, "recent channel: " + channel);
-            }
-        }
-        return list;
-    }
-
     @VisibleForTesting
     WatchedRecord getRecord(int reverseIndex) {
         return mWatchedHistory.get(mWatchedHistory.size() - 1 - reverseIndex);
diff --git a/src/com/android/tv/data/epg/EpgFetchHelper.java b/src/com/android/tv/data/epg/EpgFetchHelper.java
new file mode 100644
index 0000000..5693c87
--- /dev/null
+++ b/src/com/android/tv/data/epg/EpgFetchHelper.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2017 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.data.epg;
+
+import android.content.ContentProviderOperation;
+import android.content.Context;
+import android.content.OperationApplicationException;
+import android.database.Cursor;
+import android.media.tv.TvContract;
+import android.media.tv.TvContract.Programs;
+import android.os.RemoteException;
+import android.preference.PreferenceManager;
+import android.support.annotation.WorkerThread;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.tv.data.Program;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/** The helper class for {@link com.android.tv.data.epg.EpgFetcher} */
+class EpgFetchHelper {
+    private static final String TAG = "EpgFetchHelper";
+    private static final boolean DEBUG = false;
+
+    private static final long PROGRAM_QUERY_DURATION_MS = TimeUnit.DAYS.toMillis(30);
+    private static final int BATCH_OPERATION_COUNT = 100;
+
+    // Value: Long
+    private static final String KEY_LAST_UPDATED_EPG_TIMESTAMP =
+            "com.android.tv.data.epg.EpgFetcher.LastUpdatedEpgTimestamp";
+    // Value: String
+    private static final String KEY_LAST_LINEUP_ID =
+            "com.android.tv.data.epg.EpgFetcher.LastLineupId";
+
+    private static long sLastEpgUpdatedTimestamp = -1;
+    private static String sLastLineupId;
+
+    private EpgFetchHelper() { }
+
+    /**
+     * Updates newly fetched EPG data for the given channel to local providers. The method will
+     * compare the broadcasting time and try to match each newly fetched program with old programs
+     * of that channel in the database one by one. It will update the matched old program, or insert
+     * the new program if there is no matching program can be found in the database and at the same
+     * time remove those old programs which conflicts with the inserted one.
+
+     * @param channelId the target channel ID.
+     * @param fetchedPrograms the newly fetched program data.
+     * @return {@code true} if new program data are successfully updated. Otherwise {@code false}.
+     */
+    static boolean updateEpgData(Context context, long channelId, List<Program> fetchedPrograms) {
+        final int fetchedProgramsCount = fetchedPrograms.size();
+        if (fetchedProgramsCount == 0) {
+            return false;
+        }
+        boolean updated = false;
+        long startTimeMs = System.currentTimeMillis();
+        long endTimeMs = startTimeMs + PROGRAM_QUERY_DURATION_MS;
+        List<Program> oldPrograms = queryPrograms(context, channelId, startTimeMs, endTimeMs);
+        int oldProgramsIndex = 0;
+        int newProgramsIndex = 0;
+
+        // Compare the new programs with old programs one by one and update/delete the old one
+        // or insert new program if there is no matching program in the database.
+        ArrayList<ContentProviderOperation> ops = new ArrayList<>();
+        while (newProgramsIndex < fetchedProgramsCount) {
+            Program oldProgram = oldProgramsIndex < oldPrograms.size()
+                    ? oldPrograms.get(oldProgramsIndex) : null;
+            Program newProgram = fetchedPrograms.get(newProgramsIndex);
+            boolean addNewProgram = false;
+            if (oldProgram != null) {
+                if (oldProgram.equals(newProgram)) {
+                    // Exact match. No need to update. Move on to the next programs.
+                    oldProgramsIndex++;
+                    newProgramsIndex++;
+                } else if (hasSameTitleAndOverlap(oldProgram, newProgram)) {
+                    // Partial match. Update the old program with the new one.
+                    // NOTE: Use 'update' in this case instead of 'insert' and 'delete'. There
+                    // could be application specific settings which belong to the old program.
+                    ops.add(ContentProviderOperation.newUpdate(
+                            TvContract.buildProgramUri(oldProgram.getId()))
+                            .withValues(Program.toContentValues(newProgram))
+                            .build());
+                    oldProgramsIndex++;
+                    newProgramsIndex++;
+                } else if (oldProgram.getEndTimeUtcMillis() < newProgram.getEndTimeUtcMillis()) {
+                    // No match. Remove the old program first to see if the next program in
+                    // {@code oldPrograms} partially matches the new program.
+                    ops.add(ContentProviderOperation.newDelete(
+                            TvContract.buildProgramUri(oldProgram.getId()))
+                            .build());
+                    oldProgramsIndex++;
+                } else {
+                    // No match. The new program does not match any of the old programs. Insert
+                    // it as a new program.
+                    addNewProgram = true;
+                    newProgramsIndex++;
+                }
+            } else {
+                // No old programs. Just insert new programs.
+                addNewProgram = true;
+                newProgramsIndex++;
+            }
+            if (addNewProgram) {
+                ops.add(ContentProviderOperation
+                        .newInsert(Programs.CONTENT_URI)
+                        .withValues(Program.toContentValues(newProgram))
+                        .build());
+            }
+            // Throttle the batch operation not to cause TransactionTooLargeException.
+            if (ops.size() > BATCH_OPERATION_COUNT || newProgramsIndex >= fetchedProgramsCount) {
+                try {
+                    if (DEBUG) {
+                        int size = ops.size();
+                        Log.d(TAG, "Running " + size + " operations for channel " + channelId);
+                        for (int i = 0; i < size; ++i) {
+                            Log.d(TAG, "Operation(" + i + "): " + ops.get(i));
+                        }
+                    }
+                    context.getContentResolver().applyBatch(TvContract.AUTHORITY, ops);
+                    updated = true;
+                } catch (RemoteException | OperationApplicationException e) {
+                    Log.e(TAG, "Failed to insert programs.", e);
+                    return updated;
+                }
+                ops.clear();
+            }
+        }
+        if (DEBUG) {
+            Log.d(TAG, "Updated " + fetchedProgramsCount + " programs for channel " + channelId);
+        }
+        return updated;
+    }
+
+    private static List<Program> queryPrograms(Context context, long channelId,
+            long startTimeMs, long endTimeMs) {
+        try (Cursor c = context.getContentResolver().query(
+                TvContract.buildProgramsUriForChannel(channelId, startTimeMs, endTimeMs),
+                Program.PROJECTION, null, null, Programs.COLUMN_START_TIME_UTC_MILLIS)) {
+            if (c == null) {
+                return Collections.emptyList();
+            }
+            ArrayList<Program> programs = new ArrayList<>();
+            while (c.moveToNext()) {
+                programs.add(Program.fromCursor(c));
+            }
+            return programs;
+        }
+    }
+
+    /**
+     * Returns {@code true} if the {@code oldProgram} needs to be updated with the
+     * {@code newProgram}.
+     */
+    private static boolean hasSameTitleAndOverlap(Program oldProgram, Program newProgram) {
+        // NOTE: Here, we update the old program if it has the same title and overlaps with the
+        // new program. The test logic is just an example and you can modify this. E.g. check
+        // whether the both programs have the same program ID if your EPG supports any ID for
+        // the programs.
+        return TextUtils.equals(oldProgram.getTitle(), newProgram.getTitle())
+                && oldProgram.getStartTimeUtcMillis() <= newProgram.getEndTimeUtcMillis()
+                && newProgram.getStartTimeUtcMillis() <= oldProgram.getEndTimeUtcMillis();
+    }
+
+    /**
+     * Sets the last known lineup ID into shared preferences for future usage. If channels are not
+     * re-scanned, EPG fetcher can directly use this value instead of checking the correct lineup ID
+     * every time when it needs to fetch EPG data.
+     */
+    @WorkerThread
+    synchronized static void setLastLineupId(Context context, String lineupId) {
+        if (DEBUG) {
+            if (lineupId == null) {
+                Log.d(TAG, "Clear stored lineup id: " + sLastLineupId);
+            }
+        }
+        sLastLineupId = lineupId;
+        PreferenceManager.getDefaultSharedPreferences(context).edit()
+                .putString(KEY_LAST_LINEUP_ID, lineupId).apply();
+    }
+
+    /**
+     * Gets the last known lineup ID from shared preferences.
+     */
+    synchronized static String getLastLineupId(Context context) {
+        if (sLastLineupId == null) {
+            sLastLineupId = PreferenceManager.getDefaultSharedPreferences(context)
+                    .getString(KEY_LAST_LINEUP_ID, null);
+        }
+        if (DEBUG) Log.d(TAG, "Last lineup is " + sLastLineupId);
+        return sLastLineupId;
+    }
+
+    /**
+     * Sets the last updated timestamp of EPG data into shared preferences. If the EPG data is not
+     * out-dated, it's not necessary for EPG fetcher to fetch EPG again.
+     */
+    @WorkerThread
+    synchronized static void setLastEpgUpdatedTimestamp(Context context, long timestamp) {
+        sLastEpgUpdatedTimestamp = timestamp;
+        PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(
+                KEY_LAST_UPDATED_EPG_TIMESTAMP, timestamp).apply();
+    }
+
+    /**
+     * Gets the last updated timestamp of EPG data.
+     */
+    synchronized static long getLastEpgUpdatedTimestamp(Context context) {
+        if (sLastEpgUpdatedTimestamp < 0) {
+            sLastEpgUpdatedTimestamp = PreferenceManager.getDefaultSharedPreferences(context)
+                    .getLong(KEY_LAST_UPDATED_EPG_TIMESTAMP, 0);
+        }
+        return sLastEpgUpdatedTimestamp;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/data/epg/EpgFetcher.java b/src/com/android/tv/data/epg/EpgFetcher.java
index 3b093b6..24f8b82 100644
--- a/src/com/android/tv/data/epg/EpgFetcher.java
+++ b/src/com/android/tv/data/epg/EpgFetcher.java
@@ -16,570 +16,720 @@
 
 package com.android.tv.data.epg;
 
-import android.Manifest;
-import android.annotation.SuppressLint;
-import android.content.ContentProviderOperation;
-import android.content.ContentValues;
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.ComponentName;
 import android.content.Context;
-import android.content.OperationApplicationException;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.location.Address;
-import android.media.tv.TvContentRating;
-import android.media.tv.TvContract;
-import android.media.tv.TvContract.Programs;
-import android.media.tv.TvContract.Programs.Genres;
 import android.media.tv.TvInputInfo;
+import android.net.TrafficStats;
+import android.os.AsyncTask;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.os.RemoteException;
-import android.preference.PreferenceManager;
+import android.support.annotation.AnyThread;
 import android.support.annotation.MainThread;
-import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.v4.os.BuildCompat;
+import android.support.annotation.WorkerThread;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.tv.ApplicationSingletons;
+import com.android.tv.Features;
 import com.android.tv.TvApplication;
-import com.android.tv.common.WeakHandler;
+import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.TvCommonUtils;
+import com.android.tv.config.RemoteConfigUtils;
 import com.android.tv.data.Channel;
 import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.InternalDataUtils;
+import com.android.tv.data.ChannelLogoFetcher;
 import com.android.tv.data.Lineup;
 import com.android.tv.data.Program;
+import com.android.tv.perf.EventNames;
+import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.perf.TimerEvent;
+import com.android.tv.tuner.util.PostalCodeUtils;
 import com.android.tv.util.LocationUtils;
-import com.android.tv.util.RecurringRunner;
+import com.android.tv.util.NetworkTrafficTags;
 import com.android.tv.util.Utils;
 
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 /**
- * An utility class to fetch the EPG. This class isn't thread-safe.
+ * The service class to fetch EPG routinely or on-demand during channel scanning
+ *
+ * <p>Since the default executor of {@link AsyncTask} is {@link AsyncTask#SERIAL_EXECUTOR}, only one
+ * task can run at a time. Because fetching EPG takes long time, the fetching task shouldn't run on
+ * the serial executor. Instead, it should run on the {@link AsyncTask#THREAD_POOL_EXECUTOR}.
  */
 public class EpgFetcher {
     private static final String TAG = "EpgFetcher";
     private static final boolean DEBUG = false;
 
-    private static final int MSG_FETCH_EPG = 1;
+    private static final int EPG_ROUTINELY_FETCHING_JOB_ID = 101;
 
-    private static final long EPG_PREFETCH_RECURRING_PERIOD_MS = TimeUnit.HOURS.toMillis(4);
-    private static final long EPG_READER_INIT_WAIT_MS = TimeUnit.MINUTES.toMillis(1);
-    private static final long LOCATION_INIT_WAIT_MS = TimeUnit.SECONDS.toMillis(10);
-    private static final long LOCATION_ERROR_WAIT_MS = TimeUnit.HOURS.toMillis(1);
-    private static final long PROGRAM_QUERY_DURATION = TimeUnit.DAYS.toMillis(30);
+    private static final long INITIAL_BACKOFF_MS = TimeUnit.SECONDS.toMillis(10);
 
-    private static final int BATCH_OPERATION_COUNT = 100;
+    private static final int REASON_EPG_READER_NOT_READY = 1;
+    private static final int REASON_LOCATION_INFO_UNAVAILABLE = 2;
+    private static final int REASON_LOCATION_PERMISSION_NOT_GRANTED = 3;
+    private static final int REASON_NO_EPG_DATA_RETURNED = 4;
+    private static final int REASON_NO_NEW_EPG = 5;
 
-    private static final String SUPPORTED_COUNTRY_CODE = Locale.US.getCountry();
-    private static final String CONTENT_RATING_SEPARATOR = ",";
+    private static final long FETCH_DURING_SCAN_WAIT_TIME_MS = TimeUnit.SECONDS.toMillis(10);
 
-    // Value: Long
-    private static final String KEY_LAST_UPDATED_EPG_TIMESTAMP =
-            "com.android.tv.data.epg.EpgFetcher.LastUpdatedEpgTimestamp";
-    // Value: String
-    private static final String KEY_LAST_LINEUP_ID =
-            "com.android.tv.data.epg.EpgFetcher.LastLineupId";
+    private static final long FETCH_DURING_SCAN_DURATION_SEC = TimeUnit.HOURS.toSeconds(3);
+    private static final long FAST_FETCH_DURATION_SEC = TimeUnit.DAYS.toSeconds(2);
+
+    private static final int DEFAULT_ROUTINE_INTERVAL_HOUR = 4;
+    private static final String KEY_ROUTINE_INTERVAL = "live_channels_epg_fetcher_interval_hour";
+
+    private static final int MSG_PREPARE_FETCH_DURING_SCAN = 1;
+    private static final int MSG_CHANNEL_UPDATED_DURING_SCAN = 2;
+    private static final int MSG_FINISH_FETCH_DURING_SCAN = 3;
+    private static final int MSG_RETRY_PREPARE_FETCH_DURING_SCAN = 4;
+
+    private static final int QUERY_CHANNEL_COUNT = 50;
+    private static final int MINIMUM_CHANNELS_TO_DECIDE_LINEUP = 3;
 
     private static EpgFetcher sInstance;
 
     private final Context mContext;
     private final ChannelDataManager mChannelDataManager;
     private final EpgReader mEpgReader;
-    private EpgFetcherHandler mHandler;
-    private RecurringRunner mRecurringRunner;
-    private boolean mStarted;
+    private final PerformanceMonitor mPerformanceMonitor;
+    private FetchAsyncTask mFetchTask;
+    private FetchDuringScanHandler mFetchDuringScanHandler;
+    private long mEpgTimeStamp;
+    private List<Lineup> mPossibleLineups;
+    private final Object mPossibleLineupsLock = new Object();
+    private final Object mFetchDuringScanHandlerLock = new Object();
+    // A flag to block the re-entrance of onChannelScanStarted and onChannelScanFinished.
+    private boolean mScanStarted;
 
-    private long mLastEpgTimestamp = -1;
-    private String mLineupId;
+    private final long mRoutineIntervalMs;
+    private final long mEpgDataExpiredTimeLimitMs;
+    private final long mFastFetchDurationSec;
 
-    public static synchronized EpgFetcher getInstance(Context context) {
+    public static EpgFetcher getInstance(Context context) {
         if (sInstance == null) {
-            sInstance = new EpgFetcher(context.getApplicationContext());
+            sInstance = new EpgFetcher(context);
         }
         return sInstance;
     }
 
-    /**
-     * Creates and returns {@link EpgReader}.
-     */
-    public static EpgReader createEpgReader(Context context) {
+    /** Creates and returns {@link EpgReader}. */
+    public static EpgReader createEpgReader(Context context, String region) {
         return new StubEpgReader(context);
     }
 
     private EpgFetcher(Context context) {
-        mContext = context;
-        mEpgReader = new StubEpgReader(mContext);
-        mChannelDataManager = TvApplication.getSingletons(context).getChannelDataManager();
-        mChannelDataManager.addListener(new ChannelDataManager.Listener() {
-            @Override
-            public void onLoadFinished() {
-                if (DEBUG) Log.d(TAG, "ChannelDataManager.onLoadFinished()");
-                handleChannelChanged();
-            }
+        mContext = context.getApplicationContext();
+        ApplicationSingletons applicationSingletons = TvApplication.getSingletons(mContext);
+        mChannelDataManager = applicationSingletons.getChannelDataManager();
+        mPerformanceMonitor = applicationSingletons.getPerformanceMonitor();
+        mEpgReader = createEpgReader(mContext, LocationUtils.getCurrentCountry(mContext));
 
-            @Override
-            public void onChannelListUpdated() {
-                if (DEBUG) Log.d(TAG, "ChannelDataManager.onChannelListUpdated()");
-                handleChannelChanged();
-            }
-
-            @Override
-            public void onChannelBrowsableChanged() {
-                if (DEBUG) Log.d(TAG, "ChannelDataManager.onChannelBrowsableChanged()");
-                handleChannelChanged();
-            }
-        });
+        int remoteInteval =
+                (int) RemoteConfigUtils.getRemoteConfig(
+                        context, KEY_ROUTINE_INTERVAL, DEFAULT_ROUTINE_INTERVAL_HOUR);
+        mRoutineIntervalMs =
+                remoteInteval < 0
+                        ? TimeUnit.HOURS.toMillis(DEFAULT_ROUTINE_INTERVAL_HOUR)
+                        : TimeUnit.HOURS.toMillis(remoteInteval);
+        mEpgDataExpiredTimeLimitMs = mRoutineIntervalMs * 2;
+        mFastFetchDurationSec = FAST_FETCH_DURATION_SEC + mRoutineIntervalMs / 1000;
     }
 
-    private void handleChannelChanged() {
-        if (mStarted) {
-            if (needToStop()) {
-                stop();
+    /**
+     * Starts the routine service of EPG fetching. It use {@link JobScheduler} to schedule the EPG
+     * fetching routine. The EPG fetching routine will be started roughly every 4 hours, unless
+     * the channel scanning of tuner input is started.
+     */
+    @MainThread
+    public void startRoutineService() {
+        JobScheduler jobScheduler =
+                (JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+        for (JobInfo job : jobScheduler.getAllPendingJobs()) {
+            if (job.getId() == EPG_ROUTINELY_FETCHING_JOB_ID) {
+                return;
             }
+        }
+        JobInfo job =
+                new JobInfo.Builder(
+                                EPG_ROUTINELY_FETCHING_JOB_ID,
+                                new ComponentName(mContext, EpgFetchService.class))
+                        .setPeriodic(mRoutineIntervalMs)
+                        .setBackoffCriteria(INITIAL_BACKOFF_MS, JobInfo.BACKOFF_POLICY_EXPONENTIAL)
+                        .setPersisted(true)
+                        .build();
+        jobScheduler.schedule(job);
+        Log.i(TAG, "EPG fetching routine service started.");
+    }
+
+    /**
+     * Fetches EPG immediately if current EPG data are out-dated, i.e., not successfully updated
+     * by routine fetching service due to various reasons.
+     */
+    @MainThread
+    public void fetchImmediatelyIfNeeded() {
+        if (TvCommonUtils.isRunningInTest()) {
+            // Do not run EpgFetcher in test.
+            return;
+        }
+        new AsyncTask<Void, Void, Long>() {
+            @Override
+            protected Long doInBackground(Void... args) {
+                return EpgFetchHelper.getLastEpgUpdatedTimestamp(mContext);
+            }
+
+            @Override
+            protected void onPostExecute(Long result) {
+                if (System.currentTimeMillis() - EpgFetchHelper.getLastEpgUpdatedTimestamp(mContext)
+                        > mEpgDataExpiredTimeLimitMs) {
+                    Log.i(TAG, "EPG data expired. Start fetching immediately.");
+                    fetchImmediately();
+                }
+            }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
+
+    /**
+     * Fetches EPG immediately.
+     */
+    @MainThread
+    public void fetchImmediately() {
+        if (!mChannelDataManager.isDbLoadFinished()) {
+            mChannelDataManager.addListener(new ChannelDataManager.Listener() {
+                @Override
+                public void onLoadFinished() {
+                    mChannelDataManager.removeListener(this);
+                    executeFetchTaskIfPossible(null, null);
+                }
+
+                @Override
+                public void onChannelListUpdated() { }
+
+                @Override
+                public void onChannelBrowsableChanged() { }
+            });
         } else {
-            start();
+            executeFetchTaskIfPossible(null, null);
         }
     }
 
-    private boolean needToStop() {
-        return !canStart();
-    }
-
-    private boolean canStart() {
-        if (DEBUG) Log.d(TAG, "canStart()");
-        boolean hasInternalTunerChannel = false;
-        for (TvInputInfo input : TvApplication.getSingletons(mContext).getTvInputManagerHelper()
-                .getTvInputInfos(true, true)) {
-            String inputId = input.getId();
-            if (Utils.isInternalTvInput(mContext, inputId)
-                    && mChannelDataManager.getChannelCountForInput(inputId) > 0) {
-                hasInternalTunerChannel = true;
-                break;
+    /**
+     * Notifies EPG fetch service that channel scanning is started.
+     */
+    @MainThread
+    public void onChannelScanStarted() {
+        if (mScanStarted || !Features.ENABLE_CLOUD_EPG_REGION.isEnabled(mContext)) {
+            return;
+        }
+        mScanStarted = true;
+        stopFetchingJob();
+        synchronized (mFetchDuringScanHandlerLock) {
+            if (mFetchDuringScanHandler == null) {
+                HandlerThread thread = new HandlerThread("EpgFetchDuringScan");
+                thread.start();
+                mFetchDuringScanHandler = new FetchDuringScanHandler(thread.getLooper());
             }
+            mFetchDuringScanHandler.sendEmptyMessage(MSG_PREPARE_FETCH_DURING_SCAN);
         }
-        if (!hasInternalTunerChannel) {
-            if (DEBUG) Log.d(TAG, "No internal tuner channels.");
-            return false;
-        }
+        Log.i(TAG, "EPG fetching on channel scanning started.");
+    }
 
-        if (!TextUtils.isEmpty(getLastLineupId())) {
+    /**
+     * Notifies EPG fetch service that channel scanning is finished.
+     */
+    @MainThread
+    public void onChannelScanFinished() {
+        if (!mScanStarted) {
+            return;
+        }
+        mScanStarted = false;
+        mFetchDuringScanHandler.sendEmptyMessage(MSG_FINISH_FETCH_DURING_SCAN);
+    }
+
+    @MainThread
+    private void stopFetchingJob() {
+        if (DEBUG) Log.d(TAG, "Try to stop routinely fetching job...");
+        if (mFetchTask != null) {
+            mFetchTask.cancel(true);
+            mFetchTask = null;
+            Log.i(TAG, "EPG routinely fetching job stopped.");
+        }
+    }
+
+    @MainThread
+    private boolean executeFetchTaskIfPossible(JobService service, JobParameters params) {
+        SoftPreconditions.checkState(mChannelDataManager.isDbLoadFinished());
+        if (!TvCommonUtils.isRunningInTest() && checkFetchPrerequisite()) {
+            mFetchTask = new FetchAsyncTask(service, params);
+            mFetchTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
             return true;
         }
-        if (mContext.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
-                != PackageManager.PERMISSION_GRANTED) {
-            if (DEBUG) Log.d(TAG, "No permission to check the current location.");
+        return false;
+    }
+
+    @MainThread
+    private boolean checkFetchPrerequisite() {
+        if (DEBUG) Log.d(TAG, "Check prerequisite of routinely fetching job.");
+        if (!Features.ENABLE_CLOUD_EPG_REGION.isEnabled(mContext)) {
+            Log.i(TAG, "Cannot start routine service: country not supported: "
+                    + LocationUtils.getCurrentCountry(mContext));
             return false;
         }
-
-        try {
-            Address address = LocationUtils.getCurrentAddress(mContext);
-            if (address != null
-                    && !TextUtils.equals(address.getCountryCode(), SUPPORTED_COUNTRY_CODE)) {
-                if (DEBUG) Log.d(TAG, "Country not supported: " + address.getCountryCode());
-                return false;
-            }
-        } catch (SecurityException e) {
-            Log.w(TAG, "No permission to get the current location", e);
+        if (mFetchTask != null) {
+            // Fetching job is already running or ready to run, no need to start again.
             return false;
-        } catch (IOException e) {
-            Log.w(TAG, "IO Exception when getting the current location", e);
+        }
+        if (mFetchDuringScanHandler != null) {
+            if (DEBUG) Log.d(TAG, "Cannot start routine service: scanning channels.");
+            return false;
+        }
+        if (getTunerChannelCount() == 0) {
+            if (DEBUG) Log.d(TAG, "Cannot start routine service: no internal tuner channels.");
+            return false;
+        }
+        if (!TextUtils.isEmpty(EpgFetchHelper.getLastLineupId(mContext))) {
+            return true;
+        }
+        if (!TextUtils.isEmpty(PostalCodeUtils.getLastPostalCode(mContext))) {
+            return true;
         }
         return true;
     }
 
-    /**
-     * Starts fetching EPG.
-     */
     @MainThread
-    public void start() {
-        if (DEBUG) Log.d(TAG, "start()");
-        if (mStarted) {
-            if (DEBUG) Log.d(TAG, "EpgFetcher thread already started.");
-            return;
+    private int getTunerChannelCount() {
+        for (TvInputInfo input : TvApplication.getSingletons(mContext)
+                .getTvInputManagerHelper().getTvInputInfos(true, true)) {
+            String inputId = input.getId();
+            if (Utils.isInternalTvInput(mContext, inputId)) {
+                return mChannelDataManager.getChannelCountForInput(inputId);
+            }
         }
-        if (!canStart()) {
-            return;
-        }
-        mStarted = true;
-        if (DEBUG) Log.d(TAG, "Starting EpgFetcher thread.");
-        HandlerThread handlerThread = new HandlerThread("EpgFetcher");
-        handlerThread.start();
-        mHandler = new EpgFetcherHandler(handlerThread.getLooper(), this);
-        mRecurringRunner = new RecurringRunner(mContext, EPG_PREFETCH_RECURRING_PERIOD_MS,
-                new EpgRunner(), null);
-        mRecurringRunner.start();
-        if (DEBUG) Log.d(TAG, "EpgFetcher thread started successfully.");
+        return 0;
     }
 
-    /**
-     * Starts fetching EPG immediately if possible without waiting for the timer.
-     */
-    @MainThread
-    public void startImmediately() {
-        start();
-        if (mStarted) {
-            if (DEBUG) Log.d(TAG, "Starting fetcher immediately");
-            fetchEpg();
+    @AnyThread
+    private void clearUnusedLineups(@Nullable String lineupId) {
+        synchronized (mPossibleLineupsLock) {
+            if (mPossibleLineups == null) {
+                return;
+            }
+            for (Lineup lineup : mPossibleLineups) {
+                if (!TextUtils.equals(lineupId, lineup.id)) {
+                    mEpgReader.clearCachedChannels(lineup.id);
+                }
+            }
+            mPossibleLineups = null;
         }
     }
 
-    /**
-     * Stops fetching EPG.
-     */
-    @MainThread
-    public void stop() {
-        if (DEBUG) Log.d(TAG, "stop()");
-        if (!mStarted) {
-            return;
-        }
-        mStarted = false;
-        mRecurringRunner.stop();
-        mHandler.removeCallbacksAndMessages(null);
-        mHandler.getLooper().quit();
-    }
-
-    private void fetchEpg() {
-        fetchEpg(0);
-    }
-
-    private void fetchEpg(long delay) {
-        mHandler.removeMessages(MSG_FETCH_EPG);
-        mHandler.sendEmptyMessageDelayed(MSG_FETCH_EPG, delay);
-    }
-
-    private void onFetchEpg() {
-        if (DEBUG) Log.d(TAG, "Start fetching EPG.");
+    @WorkerThread
+    private Integer prepareFetchEpg(boolean forceUpdatePossibleLineups) {
         if (!mEpgReader.isAvailable()) {
-            if (DEBUG) Log.d(TAG, "EPG reader is not temporarily available.");
-            fetchEpg(EPG_READER_INIT_WAIT_MS);
-            return;
+            Log.i(TAG, "EPG reader is temporarily unavailable.");
+            return REASON_EPG_READER_NOT_READY;
         }
-        String lineupId = getLastLineupId();
-        if (lineupId == null) {
-            Address address;
-            try {
-                address = LocationUtils.getCurrentAddress(mContext);
-            } catch (IOException e) {
-                if (DEBUG) Log.d(TAG, "Couldn't get the current location.", e);
-                fetchEpg(LOCATION_ERROR_WAIT_MS);
-                return;
-            } catch (SecurityException e) {
-                Log.w(TAG, "No permission to get the current location.");
-                return;
-            }
-            if (address == null) {
-                if (DEBUG) Log.d(TAG, "Null address returned.");
-                fetchEpg(LOCATION_INIT_WAIT_MS);
-                return;
-            }
-            if (DEBUG) Log.d(TAG, "Current location is " + address);
-
-            lineupId = getLineupForAddress(address);
-            if (lineupId != null) {
-                if (DEBUG) Log.d(TAG, "Saving lineup " + lineupId + "found for " + address);
-                setLastLineupId(lineupId);
-            } else {
-                if (DEBUG) Log.d(TAG, "No lineup found for " + address);
-                return;
-            }
-        }
-
-        // Check the EPG Timestamp.
-        long epgTimestamp = mEpgReader.getEpgTimestamp();
-        if (epgTimestamp <= getLastUpdatedEpgTimestamp()) {
+        // Checks the EPG Timestamp.
+        mEpgTimeStamp = mEpgReader.getEpgTimestamp();
+        if (mEpgTimeStamp <= EpgFetchHelper.getLastEpgUpdatedTimestamp(mContext)) {
             if (DEBUG) Log.d(TAG, "No new EPG.");
-            return;
+            return REASON_NO_NEW_EPG;
         }
-
-        boolean updated = false;
-        List<Channel> channels = mEpgReader.getChannels(lineupId);
-        for (Channel channel : channels) {
-            List<Program> programs = new ArrayList<>(mEpgReader.getPrograms(channel.getId()));
-            Collections.sort(programs);
-            if (DEBUG) {
-                Log.d(TAG, "Fetched " + programs.size() + " programs for channel " + channel);
+        // Updates postal code.
+        boolean postalCodeChanged = false;
+        try {
+            postalCodeChanged = PostalCodeUtils.updatePostalCode(mContext);
+        } catch (IOException e) {
+            if (DEBUG) Log.d(TAG, "Couldn't get the current location.", e);
+            if (TextUtils.isEmpty(PostalCodeUtils.getLastPostalCode(mContext))) {
+                return REASON_LOCATION_INFO_UNAVAILABLE;
             }
-            if (updateEpg(channel.getId(), programs)) {
-                updated = true;
+        } catch (SecurityException e) {
+            Log.w(TAG, "No permission to get the current location.");
+            if (TextUtils.isEmpty(PostalCodeUtils.getLastPostalCode(mContext))) {
+                return REASON_LOCATION_PERMISSION_NOT_GRANTED;
             }
+        } catch (PostalCodeUtils.NoPostalCodeException e) {
+            Log.i(TAG, "Cannot get address or postal code.");
+            return REASON_LOCATION_INFO_UNAVAILABLE;
         }
-
-        final boolean epgUpdated = updated;
-        setLastUpdatedEpgTimestamp(epgTimestamp);
-        mHandler.removeMessages(MSG_FETCH_EPG);
-        if (DEBUG) Log.d(TAG, "Fetching EPG is finished.");
-    }
-
-    @Nullable
-    private String getLineupForAddress(Address address) {
-        String lineup = null;
-        if (TextUtils.equals(address.getCountryCode(), SUPPORTED_COUNTRY_CODE)) {
-            String postalCode = address.getPostalCode();
-            if (!TextUtils.isEmpty(postalCode)) {
-                lineup = getLineupForPostalCode(postalCode);
+        // Updates possible lineups if necessary.
+        SoftPreconditions.checkState(mPossibleLineups == null, TAG, "Possible lineups not reset.");
+        if (postalCodeChanged || forceUpdatePossibleLineups
+                || EpgFetchHelper.getLastLineupId(mContext) == null) {
+            // To prevent main thread being blocked, though theoretically it should not happen.
+            List<Lineup> possibleLineups =
+                    mEpgReader.getLineups(PostalCodeUtils.getLastPostalCode(mContext));
+            if (possibleLineups.isEmpty()) {
+                return REASON_NO_EPG_DATA_RETURNED;
             }
-        }
-        return lineup;
-    }
-
-    @Nullable
-    private String getLineupForPostalCode(String postalCode) {
-        List<Lineup> lineups = mEpgReader.getLineups(postalCode);
-        for (Lineup lineup : lineups) {
-            // TODO(EPG): handle more than OTA digital
-            if (lineup.type == Lineup.LINEUP_BROADCAST_DIGITAL) {
-                if (DEBUG) Log.d(TAG, "Setting lineup to " + lineup.name  + "("  + lineup.id + ")");
-                return lineup.id;
+            for (Lineup lineup : possibleLineups) {
+                mEpgReader.preloadChannels(lineup.id);
             }
+            synchronized (mPossibleLineupsLock) {
+                mPossibleLineups = possibleLineups;
+            }
+            EpgFetchHelper.setLastLineupId(mContext, null);
         }
         return null;
     }
 
-    private long getLastUpdatedEpgTimestamp() {
-        if (mLastEpgTimestamp < 0) {
-            mLastEpgTimestamp = PreferenceManager.getDefaultSharedPreferences(mContext).getLong(
-                    KEY_LAST_UPDATED_EPG_TIMESTAMP, 0);
+    @WorkerThread
+    private void batchFetchEpg(List<Channel> channels, long durationSec) {
+        Log.i(TAG, "Start batch fetching (" + durationSec + ")...." + channels.size());
+        if (channels.size() == 0) {
+            return;
         }
-        return mLastEpgTimestamp;
-    }
-
-    private void setLastUpdatedEpgTimestamp(long timestamp) {
-        mLastEpgTimestamp = timestamp;
-        PreferenceManager.getDefaultSharedPreferences(mContext).edit().putLong(
-                KEY_LAST_UPDATED_EPG_TIMESTAMP, timestamp).commit();
-    }
-
-    private String getLastLineupId() {
-        if (mLineupId == null) {
-            mLineupId = PreferenceManager.getDefaultSharedPreferences(mContext)
-                    .getString(KEY_LAST_LINEUP_ID, null);
+        List<Long> queryChannelIds = new ArrayList<>(QUERY_CHANNEL_COUNT);
+        for (Channel channel : channels) {
+            queryChannelIds.add(channel.getId());
+            if (queryChannelIds.size() >= QUERY_CHANNEL_COUNT) {
+                batchUpdateEpg(mEpgReader.getPrograms(queryChannelIds, durationSec));
+                queryChannelIds.clear();
+            }
         }
-        if (DEBUG) Log.d(TAG, "Last lineup_id " + mLineupId);
-        return mLineupId;
-    }
-
-    private void setLastLineupId(String lineupId) {
-        mLineupId = lineupId;
-        PreferenceManager.getDefaultSharedPreferences(mContext).edit()
-                .putString(KEY_LAST_LINEUP_ID, lineupId).commit();
-    }
-
-    private boolean updateEpg(long channelId, List<Program> newPrograms) {
-        final int fetchedProgramsCount = newPrograms.size();
-        if (fetchedProgramsCount == 0) {
-            return false;
+        if (!queryChannelIds.isEmpty()) {
+            batchUpdateEpg(mEpgReader.getPrograms(queryChannelIds, durationSec));
         }
-        boolean updated = false;
-        long startTimeMs = System.currentTimeMillis();
-        long endTimeMs = startTimeMs + PROGRAM_QUERY_DURATION;
-        List<Program> oldPrograms = queryPrograms(channelId, startTimeMs, endTimeMs);
-        Program currentOldProgram = oldPrograms.size() > 0 ? oldPrograms.get(0) : null;
-        int oldProgramsIndex = 0;
-        int newProgramsIndex = 0;
-        // Skip the past programs. They will be automatically removed by the system.
-        if (currentOldProgram != null) {
-            long oldStartTimeUtcMillis = currentOldProgram.getStartTimeUtcMillis();
-            for (Program program : newPrograms) {
-                if (program.getEndTimeUtcMillis() > oldStartTimeUtcMillis) {
-                    break;
+    }
+
+    @WorkerThread
+    private void batchUpdateEpg(Map<Long, List<Program>> allPrograms) {
+        for (Map.Entry<Long, List<Program>> entry : allPrograms.entrySet()) {
+            List<Program> programs = entry.getValue();
+            if (programs == null) {
+                continue;
+            }
+            Collections.sort(programs);
+            Log.i(TAG, "Batch fetched " + programs.size() + " programs for channel "
+                    + entry.getKey());
+            EpgFetchHelper.updateEpgData(mContext, entry.getKey(), programs);
+        }
+    }
+
+    @Nullable
+    @WorkerThread
+    private String pickBestLineupId(List<Channel> currentChannelList) {
+        String maxLineupId = null;
+        synchronized (mPossibleLineupsLock) {
+            if (mPossibleLineups == null) {
+                return null;
+            }
+            int maxCount = 0;
+            for (Lineup lineup : mPossibleLineups) {
+                int count = getMatchedChannelCount(lineup.id, currentChannelList);
+                Log.i(TAG, lineup.name + " (" + lineup.id + ") - " + count + " matches");
+                if (count > maxCount) {
+                    maxCount = count;
+                    maxLineupId = lineup.id;
                 }
-                newProgramsIndex++;
             }
         }
-        // Compare the new programs with old programs one by one and update/delete the old one
-        // or insert new program if there is no matching program in the database.
-        ArrayList<ContentProviderOperation> ops = new ArrayList<>();
-        while (newProgramsIndex < fetchedProgramsCount) {
-            // TODO: Extract to method and make test.
-            Program oldProgram = oldProgramsIndex < oldPrograms.size()
-                    ? oldPrograms.get(oldProgramsIndex) : null;
-            Program newProgram = newPrograms.get(newProgramsIndex);
-            boolean addNewProgram = false;
-            if (oldProgram != null) {
-                if (oldProgram.equals(newProgram)) {
-                    // Exact match. No need to update. Move on to the next programs.
-                    oldProgramsIndex++;
-                    newProgramsIndex++;
-                } else if (isSameTitleAndOverlap(oldProgram, newProgram)) {
-                    // Partial match. Update the old program with the new one.
-                    // NOTE: Use 'update' in this case instead of 'insert' and 'delete'. There
-                    // could be application specific settings which belong to the old program.
-                    ops.add(ContentProviderOperation.newUpdate(
-                            TvContract.buildProgramUri(oldProgram.getId()))
-                            .withValues(toContentValues(newProgram))
-                            .build());
-                    oldProgramsIndex++;
-                    newProgramsIndex++;
-                } else if (oldProgram.getEndTimeUtcMillis()
-                        < newProgram.getEndTimeUtcMillis()) {
-                    // No match. Remove the old program first to see if the next program in
-                    // {@code oldPrograms} partially matches the new program.
-                    ops.add(ContentProviderOperation.newDelete(
-                            TvContract.buildProgramUri(oldProgram.getId()))
-                            .build());
-                    oldProgramsIndex++;
-                } else {
-                    // No match. The new program does not match any of the old programs. Insert
-                    // it as a new program.
-                    addNewProgram = true;
-                    newProgramsIndex++;
-                }
-            } else {
-                // No old programs. Just insert new programs.
-                addNewProgram = true;
-                newProgramsIndex++;
+        return maxLineupId;
+    }
+
+    @WorkerThread
+    private int getMatchedChannelCount(String lineupId, List<Channel> currentChannelList) {
+        // Construct a list of display numbers for existing channels.
+        if (currentChannelList.isEmpty()) {
+            if (DEBUG) Log.d(TAG, "No existing channel to compare");
+            return 0;
+        }
+        List<String> numbers = new ArrayList<>(currentChannelList.size());
+        for (Channel channel : currentChannelList) {
+            // We only support channels from internal tuner inputs.
+            if (Utils.isInternalTvInput(mContext, channel.getInputId())) {
+                numbers.add(channel.getDisplayNumber());
             }
-            if (addNewProgram) {
-                ops.add(ContentProviderOperation
-                        .newInsert(TvContract.Programs.CONTENT_URI)
-                        .withValues(toContentValues(newProgram))
-                        .build());
-            }
-            // Throttle the batch operation not to cause TransactionTooLargeException.
-            if (ops.size() > BATCH_OPERATION_COUNT || newProgramsIndex >= fetchedProgramsCount) {
-                try {
-                    if (DEBUG) {
-                        int size = ops.size();
-                        Log.d(TAG, "Running " + size + " operations for channel " + channelId);
-                        for (int i = 0; i < size; ++i) {
-                            Log.d(TAG, "Operation(" + i + "): " + ops.get(i));
+        }
+        numbers.retainAll(mEpgReader.getChannelNumbers(lineupId));
+        return numbers.size();
+    }
+
+    public static class EpgFetchService extends JobService {
+        private EpgFetcher mEpgFetcher;
+
+        @Override
+        public void onCreate() {
+            super.onCreate();
+            TvApplication.setCurrentRunningProcess(this, true);
+            mEpgFetcher = EpgFetcher.getInstance(this);
+        }
+
+        @Override
+        public boolean onStartJob(JobParameters params) {
+            if (!mEpgFetcher.mChannelDataManager.isDbLoadFinished()) {
+                mEpgFetcher.mChannelDataManager.addListener(new ChannelDataManager.Listener() {
+                    @Override
+                    public void onLoadFinished() {
+                        mEpgFetcher.mChannelDataManager.removeListener(this);
+                        if (!mEpgFetcher.executeFetchTaskIfPossible(EpgFetchService.this, params)) {
+                            jobFinished(params, false);
                         }
                     }
-                    mContext.getContentResolver().applyBatch(TvContract.AUTHORITY, ops);
-                    updated = true;
-                } catch (RemoteException | OperationApplicationException e) {
-                    Log.e(TAG, "Failed to insert programs.", e);
-                    return updated;
+
+                    @Override
+                    public void onChannelListUpdated() { }
+
+                    @Override
+                    public void onChannelBrowsableChanged() { }
+                });
+                return true;
+            } else {
+                return mEpgFetcher.executeFetchTaskIfPossible(this, params);
+            }
+        }
+
+        @Override
+        public boolean onStopJob(JobParameters params) {
+            mEpgFetcher.stopFetchingJob();
+            return false;
+        }
+    }
+
+    private class FetchAsyncTask extends AsyncTask<Void, Void, Integer> {
+        private final JobService mService;
+        private final JobParameters mParams;
+        private List<Channel> mCurrentChannelList;
+        private TimerEvent mTimerEvent;
+
+        private FetchAsyncTask(JobService service, JobParameters params) {
+            mService = service;
+            mParams = params;
+        }
+
+        @Override
+        protected void onPreExecute() {
+            mTimerEvent = mPerformanceMonitor.startTimer();
+            mCurrentChannelList = mChannelDataManager.getChannelList();
+        }
+
+        @Override
+        protected Integer doInBackground(Void... args) {
+            final int oldTag = TrafficStats.getThreadStatsTag();
+            TrafficStats.setThreadStatsTag(NetworkTrafficTags.EPG_FETCH);
+            try {
+                if (DEBUG) Log.d(TAG, "Start EPG routinely fetching.");
+                Integer failureReason = prepareFetchEpg(false);
+                // InterruptedException might be caught by RPC, we should check it here.
+                if (failureReason != null || this.isCancelled()) {
+                    return failureReason;
                 }
-                ops.clear();
+                String lineupId = EpgFetchHelper.getLastLineupId(mContext);
+                lineupId = lineupId == null ? pickBestLineupId(mCurrentChannelList) : lineupId;
+                if (lineupId != null) {
+                    Log.i(TAG, "Selecting the lineup " + lineupId);
+                    // During normal fetching process, the lineup ID should be confirmed since all
+                    // channels are known, clear up possible lineups to save resources.
+                    EpgFetchHelper.setLastLineupId(mContext, lineupId);
+                    clearUnusedLineups(lineupId);
+                } else {
+                    Log.i(TAG, "Failed to get lineup id");
+                    return REASON_NO_EPG_DATA_RETURNED;
+                }
+                final List<Channel> channels = mEpgReader.getChannels(lineupId);
+                // InterruptedException might be caught by RPC, we should check it here.
+                if (this.isCancelled()) {
+                    return null;
+                }
+                if (channels.isEmpty()) {
+                    Log.i(TAG, "Failed to get EPG channels.");
+                    return REASON_NO_EPG_DATA_RETURNED;
+                }
+                if (System.currentTimeMillis() - EpgFetchHelper.getLastEpgUpdatedTimestamp(mContext)
+                        > mEpgDataExpiredTimeLimitMs) {
+                    batchFetchEpg(channels, mFastFetchDurationSec);
+                }
+                new Handler(mContext.getMainLooper())
+                        .post(
+                                new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        ChannelLogoFetcher.startFetchingChannelLogos(
+                                                mContext, channels);
+                                    }
+                                });
+                for (Channel channel : channels) {
+                    if (this.isCancelled()) {
+                        return null;
+                    }
+                    long channelId = channel.getId();
+                    List<Program> programs = new ArrayList<>(mEpgReader.getPrograms(channelId));
+                    // InterruptedException might be caught by RPC, we should check it here.
+                    Collections.sort(programs);
+                    Log.i(TAG, "Fetched " + programs.size() + " programs for channel " + channelId);
+                    EpgFetchHelper.updateEpgData(mContext, channelId, programs);
+                }
+                EpgFetchHelper.setLastEpgUpdatedTimestamp(mContext, mEpgTimeStamp);
+                if (DEBUG) Log.d(TAG, "Fetching EPG is finished.");
+                return null;
+            } finally {
+                TrafficStats.setThreadStatsTag(oldTag);
             }
         }
-        if (DEBUG) {
-            Log.d(TAG, "Updated " + fetchedProgramsCount + " programs for channel " + channelId);
-        }
-        return updated;
-    }
-
-    private List<Program> queryPrograms(long channelId, long startTimeMs, long endTimeMs) {
-        try (Cursor c = mContext.getContentResolver().query(
-                TvContract.buildProgramsUriForChannel(channelId, startTimeMs, endTimeMs),
-                Program.PROJECTION, null, null, Programs.COLUMN_START_TIME_UTC_MILLIS)) {
-            if (c == null) {
-                return Collections.emptyList();
-            }
-            ArrayList<Program> programs = new ArrayList<>();
-            while (c.moveToNext()) {
-                programs.add(Program.fromCursor(c));
-            }
-            return programs;
-        }
-    }
-
-    /**
-     * Returns {@code true} if the {@code oldProgram} program needs to be updated with the
-     * {@code newProgram} program.
-     */
-    private boolean isSameTitleAndOverlap(Program oldProgram, Program newProgram) {
-        // NOTE: Here, we update the old program if it has the same title and overlaps with the
-        // new program. The test logic is just an example and you can modify this. E.g. check
-        // whether the both programs have the same program ID if your EPG supports any ID for
-        // the programs.
-        return Objects.equals(oldProgram.getTitle(), newProgram.getTitle())
-                && oldProgram.getStartTimeUtcMillis() <= newProgram.getEndTimeUtcMillis()
-                && newProgram.getStartTimeUtcMillis() <= oldProgram.getEndTimeUtcMillis();
-    }
-
-    @SuppressLint("InlinedApi")
-    @SuppressWarnings("deprecation")
-    private static ContentValues toContentValues(Program program) {
-        ContentValues values = new ContentValues();
-        values.put(TvContract.Programs.COLUMN_CHANNEL_ID, program.getChannelId());
-        putValue(values, TvContract.Programs.COLUMN_TITLE, program.getTitle());
-        putValue(values, TvContract.Programs.COLUMN_EPISODE_TITLE, program.getEpisodeTitle());
-        if (BuildCompat.isAtLeastN()) {
-            putValue(values, TvContract.Programs.COLUMN_SEASON_DISPLAY_NUMBER,
-                    program.getSeasonNumber());
-            putValue(values, TvContract.Programs.COLUMN_EPISODE_DISPLAY_NUMBER,
-                    program.getEpisodeNumber());
-        } else {
-            putValue(values, TvContract.Programs.COLUMN_SEASON_NUMBER, program.getSeasonNumber());
-            putValue(values, TvContract.Programs.COLUMN_EPISODE_NUMBER, program.getEpisodeNumber());
-        }
-        putValue(values, TvContract.Programs.COLUMN_SHORT_DESCRIPTION, program.getDescription());
-        putValue(values, TvContract.Programs.COLUMN_POSTER_ART_URI, program.getPosterArtUri());
-        putValue(values, TvContract.Programs.COLUMN_THUMBNAIL_URI, program.getThumbnailUri());
-        String[] canonicalGenres = program.getCanonicalGenres();
-        if (canonicalGenres != null && canonicalGenres.length > 0) {
-            putValue(values, TvContract.Programs.COLUMN_CANONICAL_GENRE,
-                    Genres.encode(canonicalGenres));
-        } else {
-            putValue(values, TvContract.Programs.COLUMN_CANONICAL_GENRE, "");
-        }
-        TvContentRating[] ratings = program.getContentRatings();
-        if (ratings != null && ratings.length > 0) {
-            StringBuilder sb = new StringBuilder(ratings[0].flattenToString());
-            for (int i = 1; i < ratings.length; ++i) {
-                sb.append(CONTENT_RATING_SEPARATOR);
-                sb.append(ratings[i].flattenToString());
-            }
-            putValue(values, TvContract.Programs.COLUMN_CONTENT_RATING, sb.toString());
-        } else {
-            putValue(values, TvContract.Programs.COLUMN_CONTENT_RATING, "");
-        }
-        values.put(TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS,
-                program.getStartTimeUtcMillis());
-        values.put(TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS, program.getEndTimeUtcMillis());
-        putValue(values, TvContract.Programs.COLUMN_INTERNAL_PROVIDER_DATA,
-                InternalDataUtils.serializeInternalProviderData(program));
-        return values;
-    }
-
-    private static void putValue(ContentValues contentValues, String key, String value) {
-        if (TextUtils.isEmpty(value)) {
-            contentValues.putNull(key);
-        } else {
-            contentValues.put(key, value);
-        }
-    }
-
-    private static void putValue(ContentValues contentValues, String key, byte[] value) {
-        if (value == null || value.length == 0) {
-            contentValues.putNull(key);
-        } else {
-            contentValues.put(key, value);
-        }
-    }
-
-    private static class EpgFetcherHandler extends WeakHandler<EpgFetcher> {
-        public EpgFetcherHandler (@NonNull Looper looper, EpgFetcher ref) {
-            super(looper, ref);
-        }
 
         @Override
-        public void handleMessage(Message msg, @NonNull EpgFetcher epgFetcher) {
+        protected void onPostExecute(Integer failureReason) {
+            mFetchTask = null;
+            if (failureReason == null || failureReason == REASON_LOCATION_PERMISSION_NOT_GRANTED
+                    || failureReason == REASON_NO_NEW_EPG) {
+                jobFinished(false);
+            } else {
+                // Applies back-off policy
+                jobFinished(true);
+            }
+            mPerformanceMonitor.stopTimer(mTimerEvent, EventNames.FETCH_EPG_TASK);
+            mPerformanceMonitor.recordMemory(EventNames.FETCH_EPG_TASK);
+        }
+
+        @Override
+        protected void onCancelled(Integer failureReason) {
+            clearUnusedLineups(null);
+            jobFinished(false);
+        }
+
+        private void jobFinished(boolean reschedule) {
+            if (mService != null && mParams != null) {
+                // Task is executed from JobService, need to report jobFinished.
+                mService.jobFinished(mParams, reschedule);
+            }
+        }
+    }
+
+    @WorkerThread
+    private class FetchDuringScanHandler extends Handler {
+        private final Set<Long> mFetchedChannelIdsDuringScan = new HashSet<>();
+        private String mPossibleLineupId;
+
+        private final ChannelDataManager.Listener mDuringScanChannelListener =
+                new ChannelDataManager.Listener() {
+                    @Override
+                    public void onLoadFinished() {
+                        if (DEBUG) Log.d(TAG, "ChannelDataManager.onLoadFinished()");
+                        if (getTunerChannelCount() >= MINIMUM_CHANNELS_TO_DECIDE_LINEUP
+                                && !hasMessages(MSG_CHANNEL_UPDATED_DURING_SCAN)) {
+                            Message.obtain(FetchDuringScanHandler.this,
+                                    MSG_CHANNEL_UPDATED_DURING_SCAN, new ArrayList<>(
+                                            mChannelDataManager.getChannelList())).sendToTarget();
+                        }
+                    }
+
+                    @Override
+                    public void onChannelListUpdated() {
+                        if (DEBUG) Log.d(TAG, "ChannelDataManager.onChannelListUpdated()");
+                        if (getTunerChannelCount() >= MINIMUM_CHANNELS_TO_DECIDE_LINEUP
+                                && !hasMessages(MSG_CHANNEL_UPDATED_DURING_SCAN)) {
+                            Message.obtain(FetchDuringScanHandler.this,
+                                    MSG_CHANNEL_UPDATED_DURING_SCAN,
+                                            mChannelDataManager.getChannelList()).sendToTarget();
+                        }
+                    }
+
+                    @Override
+                    public void onChannelBrowsableChanged() {
+                        // Do nothing
+                    }
+                };
+
+        @AnyThread
+        private FetchDuringScanHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
             switch (msg.what) {
-                case MSG_FETCH_EPG:
-                    epgFetcher.onFetchEpg();
+                case MSG_PREPARE_FETCH_DURING_SCAN:
+                case MSG_RETRY_PREPARE_FETCH_DURING_SCAN:
+                    onPrepareFetchDuringScan();
                     break;
-                default:
-                    super.handleMessage(msg);
+                case MSG_CHANNEL_UPDATED_DURING_SCAN:
+                    if (!hasMessages(MSG_CHANNEL_UPDATED_DURING_SCAN)) {
+                        onChannelUpdatedDuringScan((List<Channel>) msg.obj);
+                    }
+                    break;
+                case MSG_FINISH_FETCH_DURING_SCAN:
+                    removeMessages(MSG_RETRY_PREPARE_FETCH_DURING_SCAN);
+                    if (hasMessages(MSG_CHANNEL_UPDATED_DURING_SCAN)) {
+                        sendEmptyMessage(MSG_FINISH_FETCH_DURING_SCAN);
+                    } else {
+                        onFinishFetchDuringScan();
+                    }
                     break;
             }
         }
-    }
 
-    private class EpgRunner implements Runnable {
-        @Override
-        public void run() {
-            fetchEpg();
+        private void onPrepareFetchDuringScan() {
+            Integer failureReason = prepareFetchEpg(true);
+            if (failureReason != null) {
+                sendEmptyMessageDelayed(
+                        MSG_RETRY_PREPARE_FETCH_DURING_SCAN, FETCH_DURING_SCAN_WAIT_TIME_MS);
+                return;
+            }
+            mChannelDataManager.addListener(mDuringScanChannelListener);
+        }
+
+        private void onChannelUpdatedDuringScan(List<Channel> currentChannelList) {
+            String lineupId = pickBestLineupId(currentChannelList);
+            Log.i(TAG, "Fast fetch channels for lineup ID: " + lineupId);
+            if (TextUtils.isEmpty(lineupId)) {
+                if (TextUtils.isEmpty(mPossibleLineupId)) {
+                    return;
+                }
+            } else if (!TextUtils.equals(lineupId, mPossibleLineupId)) {
+                mFetchedChannelIdsDuringScan.clear();
+                mPossibleLineupId = lineupId;
+            }
+            List<Long> currentChannelIds = new ArrayList<>();
+            for (Channel channel : currentChannelList) {
+                currentChannelIds.add(channel.getId());
+            }
+            mFetchedChannelIdsDuringScan.retainAll(currentChannelIds);
+            List<Channel> newChannels = new ArrayList<>();
+            for (Channel channel : mEpgReader.getChannels(mPossibleLineupId)) {
+                if (!mFetchedChannelIdsDuringScan.contains(channel.getId())) {
+                    newChannels.add(channel);
+                    mFetchedChannelIdsDuringScan.add(channel.getId());
+                }
+            }
+            batchFetchEpg(newChannels, FETCH_DURING_SCAN_DURATION_SEC);
+        }
+
+        private void onFinishFetchDuringScan() {
+            mChannelDataManager.removeListener(mDuringScanChannelListener);
+            EpgFetchHelper.setLastLineupId(mContext, mPossibleLineupId);
+            clearUnusedLineups(null);
+            mFetchedChannelIdsDuringScan.clear();
+            synchronized (mFetchDuringScanHandlerLock) {
+                if (!hasMessages(MSG_PREPARE_FETCH_DURING_SCAN)) {
+                    removeCallbacksAndMessages(null);
+                    getLooper().quit();
+                    mFetchDuringScanHandler = null;
+                }
+            }
+            // Clear timestamp to make routine service start right away.
+            EpgFetchHelper.setLastEpgUpdatedTimestamp(mContext, 0);
+            Log.i(TAG, "EPG Fetching during channel scanning finished.");
+            new Handler(Looper.getMainLooper()).post(new Runnable() {
+                @Override
+                public void run() {
+                    fetchImmediately();
+                }
+            });
         }
     }
 }
diff --git a/src/com/android/tv/data/epg/EpgReader.java b/src/com/android/tv/data/epg/EpgReader.java
index 4f3b6f5..c5aeca2 100644
--- a/src/com/android/tv/data/epg/EpgReader.java
+++ b/src/com/android/tv/data/epg/EpgReader.java
@@ -16,15 +16,17 @@
 
 package com.android.tv.data.epg;
 
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.WorkerThread;
 
 import com.android.tv.data.Channel;
 import com.android.tv.data.Lineup;
 import com.android.tv.data.Program;
-import com.android.tv.dvr.SeriesInfo;
+import com.android.tv.dvr.data.SeriesInfo;
 
 import java.util.List;
+import java.util.Map;
 
 /**
  * An interface used to retrieve the EPG data. This class should be used in worker thread.
@@ -42,25 +44,48 @@
      */
     long getEpgTimestamp();
 
-    /**
-     * Returns the channels list.
-     */
-    List<Channel> getChannels(@NonNull String lineupId);
+    /** Sets the region code. */
+    void setRegionCode(String regionCode);
 
-    /**
-     * Returns the lineups list.
-     */
+    /** Returns the lineups list. */
     List<Lineup> getLineups(@NonNull String postalCode);
 
     /**
-     * Returns the programs for the given channel. The result is sorted by the start time.
-     * Note that the {@code Program} doesn't have valid program ID because it's not retrieved from
-     * TvProvider.
+     * Returns the list of channel numbers (unsorted) for the given lineup. The result is used to
+     * choose the most appropriate lineup among others by comparing the channel numbers of the
+     * existing channels on the device.
+     */
+    List<String> getChannelNumbers(@NonNull String lineupId);
+
+    /**
+     * Returns the list of channels for the given lineup. The returned channels should map into the
+     * existing channels on the device. This method is usually called after selecting the lineup.
+     */
+    List<Channel> getChannels(@NonNull String lineupId);
+
+    /** Pre-loads and caches channels for a given lineup. */
+    void preloadChannels(@NonNull String lineupId);
+
+    /**
+     * Clears cached channels for a given lineup.
+     */
+    @AnyThread
+    void clearCachedChannels(@NonNull String lineupId);
+
+    /**
+     * Returns the programs for the given channel. Must call {@link #getChannels(String)}
+     * beforehand. Note that the {@code Program} doesn't have valid program ID because it's not
+     * retrieved from TvProvider.
      */
     List<Program> getPrograms(long channelId);
 
     /**
-     * Returns the series information for the given series ID.
+     * Returns the programs for the given channels. Note that the {@code Program} doesn't have valid
+     * program ID because it's not retrieved from TvProvider. This method is only used to get
+     * programs for a short duration typically.
      */
-    SeriesInfo getSeriesInfo(String seriesId);
-}
+    Map<Long, List<Program>> getPrograms(@NonNull List<Long> channelIds, long duration);
+
+    /** Returns the series information for the given series ID. */
+    SeriesInfo getSeriesInfo(@NonNull String seriesId);
+}
\ No newline at end of file
diff --git a/src/com/android/tv/data/epg/StubEpgReader.java b/src/com/android/tv/data/epg/StubEpgReader.java
index 64093f8..ab6935a 100644
--- a/src/com/android/tv/data/epg/StubEpgReader.java
+++ b/src/com/android/tv/data/epg/StubEpgReader.java
@@ -18,13 +18,15 @@
 
 import android.content.Context;
 
+import android.support.annotation.NonNull;
 import com.android.tv.data.Channel;
 import com.android.tv.data.Lineup;
 import com.android.tv.data.Program;
-import com.android.tv.dvr.SeriesInfo;
+import com.android.tv.dvr.data.SeriesInfo;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A stub class to read EPG.
@@ -44,22 +46,47 @@
     }
 
     @Override
-    public List<Channel> getChannels(String lineupId) {
+    public void setRegionCode(String regionCode) {
+        // Do nothing
+    }
+
+    @Override
+    public List<Lineup> getLineups(@NonNull String postalCode) {
         return Collections.emptyList();
     }
 
     @Override
-    public List<Lineup> getLineups(String postalCode) {
+    public List<String> getChannelNumbers(@NonNull String lineupId) {
         return Collections.emptyList();
     }
 
     @Override
+    public List<Channel> getChannels(@NonNull String lineupId) {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public void preloadChannels(@NonNull String lineupId) {
+        // Do nothing
+    }
+
+    @Override
+    public void clearCachedChannels(@NonNull String lineupId) {
+        // Do nothing
+    }
+
+    @Override
     public List<Program> getPrograms(long channelId) {
         return Collections.emptyList();
     }
 
     @Override
-    public SeriesInfo getSeriesInfo(String seriesId) {
+    public Map<Long, List<Program>> getPrograms(@NonNull List<Long> channelIds, long duration) {
+        return Collections.emptyMap();
+    }
+
+    @Override
+    public SeriesInfo getSeriesInfo(@NonNull String seriesId) {
         return null;
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dialog/DvrHistoryDialogFragment.java b/src/com/android/tv/dialog/DvrHistoryDialogFragment.java
new file mode 100644
index 0000000..d686e6e
--- /dev/null
+++ b/src/com/android/tv/dialog/DvrHistoryDialogFragment.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2016 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.dialog;
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.os.Build.VERSION_CODES;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.android.tv.ApplicationSingletons;
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.data.Channel;
+import com.android.tv.data.ChannelDataManager;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.ui.DvrUiHelper;
+import com.android.tv.util.Utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Displays the DVR history.
+ */
+@TargetApi(VERSION_CODES.N)
+public class DvrHistoryDialogFragment extends SafeDismissDialogFragment {
+    public static final String DIALOG_TAG = DvrHistoryDialogFragment.class.getSimpleName();
+
+    private static final String TRACKER_LABEL = "DVR history";
+    private final List<ScheduledRecording> mSchedules = new ArrayList<>();
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        ApplicationSingletons singletons = TvApplication.getSingletons(getContext());
+        DvrDataManager dataManager = singletons.getDvrDataManager();
+        ChannelDataManager channelDataManager = singletons.getChannelDataManager();
+        for (ScheduledRecording schedule : dataManager.getAllScheduledRecordings()) {
+            if (!schedule.isInProgress() && !schedule.isNotStarted()) {
+                mSchedules.add(schedule);
+            }
+        }
+        mSchedules.sort(ScheduledRecording.START_TIME_COMPARATOR.reversed());
+        LayoutInflater inflater = LayoutInflater.from(getContext());
+        ArrayAdapter adapter = new ArrayAdapter<ScheduledRecording>(getContext(),
+                R.layout.list_item_dvr_history, ScheduledRecording.toArray(mSchedules)) {
+            @NonNull
+            @Override
+            public View getView(int position, View convertView, ViewGroup parent) {
+                View view = inflater.inflate(R.layout.list_item_dvr_history, parent, false);
+                ScheduledRecording schedule = mSchedules.get(position);
+                setText(view, R.id.state, getStateString(schedule.getState()));
+                setText(view, R.id.schedule_time, getRecordingTimeText(schedule));
+                setText(view, R.id.program_title, DvrUiHelper.getStyledTitleWithEpisodeNumber(
+                        getContext(), schedule, 0));
+                setText(view, R.id.channel_name, getChannelNameText(schedule));
+                return view;
+            }
+
+            private void setText(View view, int id, CharSequence text) {
+                ((TextView) view.findViewById(id)).setText(text);
+            }
+
+            private void setText(View view, int id, int text) {
+                ((TextView) view.findViewById(id)).setText(text);
+            }
+
+            @SuppressLint("SwitchIntDef")
+            private int getStateString(@RecordingState int state) {
+                switch (state) {
+                    case ScheduledRecording.STATE_RECORDING_CLIPPED:
+                        return R.string.dvr_history_dialog_state_clip;
+                    case ScheduledRecording.STATE_RECORDING_FAILED:
+                        return R.string.dvr_history_dialog_state_fail;
+                    case ScheduledRecording.STATE_RECORDING_FINISHED:
+                        return R.string.dvr_history_dialog_state_success;
+                    default:
+                        break;
+                }
+                return 0;
+            }
+
+            private String getChannelNameText(ScheduledRecording schedule) {
+                Channel channel = channelDataManager.getChannel(schedule.getChannelId());
+                return channel == null ? null :
+                        TextUtils.isEmpty(channel.getDisplayName()) ? channel.getDisplayNumber() :
+                                channel.getDisplayName().trim() + " " + channel.getDisplayNumber();
+            }
+
+            private String getRecordingTimeText(ScheduledRecording schedule) {
+                return Utils.getDurationString(getContext(), schedule.getStartTimeMs(),
+                        schedule.getEndTimeMs(), true, true, true, 0);
+            }
+        };
+        ListView listView = new ListView(getActivity());
+        listView.setAdapter(adapter);
+        return new AlertDialog.Builder(getActivity()).setTitle(R.string.dvr_history_dialog_title)
+                .setView(listView).create();
+    }
+
+    @Override
+    public String getTrackerLabel() {
+        return TRACKER_LABEL;
+    }
+}
diff --git a/src/com/android/tv/dialog/FullscreenDialogFragment.java b/src/com/android/tv/dialog/FullscreenDialogFragment.java
index d16202a..d00422a 100644
--- a/src/com/android/tv/dialog/FullscreenDialogFragment.java
+++ b/src/com/android/tv/dialog/FullscreenDialogFragment.java
@@ -77,7 +77,7 @@
         return mTrackerLabel;
     }
 
-    private class FullscreenDialog extends TvDialog {
+    private class FullscreenDialog extends Dialog {
         public FullscreenDialog(Context context, int theme) {
             super(context, theme);
         }
diff --git a/src/com/android/tv/dvr/ui/HalfSizedDialogFragment.java b/src/com/android/tv/dialog/HalfSizedDialogFragment.java
similarity index 92%
rename from src/com/android/tv/dvr/ui/HalfSizedDialogFragment.java
rename to src/com/android/tv/dialog/HalfSizedDialogFragment.java
index d320816..315c6a9 100644
--- a/src/com/android/tv/dvr/ui/HalfSizedDialogFragment.java
+++ b/src/com/android/tv/dialog/HalfSizedDialogFragment.java
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dialog;
 
+import android.app.Dialog;
 import android.content.DialogInterface;
 import android.os.Bundle;
 import android.os.Handler;
@@ -25,7 +26,6 @@
 import android.view.ViewGroup;
 
 import com.android.tv.R;
-import com.android.tv.dialog.SafeDismissDialogFragment;
 
 import java.util.concurrent.TimeUnit;
 
@@ -54,13 +54,6 @@
     @Override
     public void onStart() {
         super.onStart();
-        getDialog().setOnKeyListener(new DialogInterface.OnKeyListener() {
-            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent keyEvent) {
-                mHandler.removeCallbacks(mAutoDismisser);
-                mHandler.postDelayed(mAutoDismisser, AUTO_DISMISS_TIME_THRESHOLD_MS);
-                return false;
-            }
-        });
         mHandler.postDelayed(mAutoDismisser, AUTO_DISMISS_TIME_THRESHOLD_MS);
     }
 
@@ -81,6 +74,19 @@
     }
 
     @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        Dialog dialog = super.onCreateDialog(savedInstanceState);
+        dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
+            public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent keyEvent) {
+                mHandler.removeCallbacks(mAutoDismisser);
+                mHandler.postDelayed(mAutoDismisser, AUTO_DISMISS_TIME_THRESHOLD_MS);
+                return false;
+            }
+        });
+        return dialog;
+    }
+
+    @Override
     public int getTheme() {
         return R.style.Theme_TV_dialog_HalfSizedDialog;
     }
diff --git a/src/com/android/tv/dialog/PinDialogFragment.java b/src/com/android/tv/dialog/PinDialogFragment.java
index d9d6c73..d5c154d 100644
--- a/src/com/android/tv/dialog/PinDialogFragment.java
+++ b/src/com/android/tv/dialog/PinDialogFragment.java
@@ -28,6 +28,7 @@
 import android.content.DialogInterface;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
+import android.media.tv.TvContentRating;
 import android.os.Bundle;
 import android.os.Handler;
 import android.preference.PreferenceManager;
@@ -45,11 +46,13 @@
 import android.widget.Toast;
 
 import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.common.SoftPreconditions;
 import com.android.tv.util.TvSettings;
 
 public class PinDialogFragment extends SafeDismissDialogFragment {
     private static final String TAG = "PinDialogFragment";
-    private static final boolean DBG = true;
+    private static final boolean DEBUG = true;
 
     /**
      * PIN code dialog for unlock channel
@@ -80,18 +83,13 @@
      */
     public static final int PIN_DIALOG_TYPE_UNLOCK_DVR = 5;
 
-    private static final int PIN_DIALOG_RESULT_SUCCESS = 0;
-    private static final int PIN_DIALOG_RESULT_FAIL = 1;
-
     private static final int MAX_WRONG_PIN_COUNT = 5;
     private static final int DISABLE_PIN_DURATION_MILLIS = 60 * 1000; // 1 minute
 
     private static final String INITIAL_TEXT = "—";
     private static final String TRACKER_LABEL = "Pin dialog";
-
-    public interface ResultListener {
-        void done(boolean success);
-    }
+    private static final String ARGS_TYPE = "args_type";
+    private static final String ARGS_RATING = "args_rating";
 
     public static final String DIALOG_TAG = PinDialogFragment.class.getName();
 
@@ -99,8 +97,9 @@
             R.id.first, R.id.second, R.id.third, R.id.fourth };
 
     private int mType;
-    private ResultListener mListener;
-    private int mRetCode;
+    private int mRequestType;
+    private boolean mPinChecked;
+    private boolean mDismissSilently;
 
     private TextView mWrongPinView;
     private View mEnterPinView;
@@ -114,29 +113,35 @@
     private long mDisablePinUntil;
     private final Handler mHandler = new Handler();
 
-    public PinDialogFragment(int type, ResultListener listener) {
-        this(type, listener, null);
+    public static PinDialogFragment create(int type) {
+        return create(type, null);
     }
 
-    public PinDialogFragment(int type, ResultListener listener, String rating) {
-        mType = type;
-        mListener = listener;
-        mRetCode = PIN_DIALOG_RESULT_FAIL;
-        mRatingString = rating;
+    public static PinDialogFragment create(int type, String rating) {
+        PinDialogFragment fragment = new PinDialogFragment();
+        Bundle args = new Bundle();
+        args.putInt(ARGS_TYPE, type);
+        args.putString(ARGS_RATING, rating);
+        fragment.setArguments(args);
+        return fragment;
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
+        mRequestType = getArguments().getInt(ARGS_TYPE, PIN_DIALOG_TYPE_ENTER_PIN);
+        mType = mRequestType;
+        mRatingString = getArguments().getString(ARGS_RATING);
         setStyle(STYLE_NO_TITLE, 0);
         mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
         mDisablePinUntil = TvSettings.getDisablePinUntil(getActivity());
         if (ActivityManager.isUserAMonkey()) {
             // Skip PIN dialog half the time for monkeys
             if (Math.random() < 0.5) {
-                exit(PIN_DIALOG_RESULT_SUCCESS);
+                exit(true);
             }
         }
+        mPinChecked = false;
     }
 
     @Override
@@ -186,7 +191,19 @@
                 mTitleView.setText(R.string.pin_enter_unlock_program);
                 break;
             case PIN_DIALOG_TYPE_UNLOCK_DVR:
-                mTitleView.setText(getString(R.string.pin_enter_unlock_dvr, mRatingString));
+                TvContentRating tvContentRating =
+                        TvContentRating.unflattenFromString(mRatingString);
+                if (TvContentRating.UNRATED.equals(tvContentRating)) {
+                    mTitleView.setText(getString(R.string.pin_enter_unlock_dvr_unrated));
+                } else {
+                    mTitleView.setText(
+                            getString(
+                                    R.string.pin_enter_unlock_dvr,
+                                    TvApplication.getSingletons(getContext())
+                                            .getTvInputManagerHelper()
+                                            .getContentRatingsManager()
+                                            .getDisplayNameForRating(tvContentRating)));
+                }
                 break;
             case PIN_DIALOG_TYPE_ENTER_PIN:
                 mTitleView.setText(R.string.pin_enter_pin);
@@ -217,10 +234,6 @@
         return v;
     }
 
-    public void setResultListener(ResultListener listener) {
-        mListener = listener;
-    }
-
     private final Runnable mUpdateEnterPinRunnable = new Runnable() {
         @Override
         public void run() {
@@ -250,18 +263,27 @@
         }
     }
 
-    private void exit(int retCode) {
-        mRetCode = retCode;
+    private void exit(boolean pinChecked) {
+        mPinChecked = pinChecked;
+        dismiss();
+    }
+
+    /** Dismisses the pin dialog without calling activity listener. */
+    public void dismissSilently() {
+        mDismissSilently = true;
         dismiss();
     }
 
     @Override
     public void onDismiss(DialogInterface dialog) {
         super.onDismiss(dialog);
-        if (DBG) Log.d(TAG, "onDismiss: mRetCode=" + mRetCode);
-        if (mListener != null) {
-            mListener.done(mRetCode == PIN_DIALOG_RESULT_SUCCESS);
+        if (DEBUG) Log.d(TAG, "onDismiss: mPinChecked=" + mPinChecked);
+        SoftPreconditions.checkState(getActivity() instanceof OnPinCheckedListener);
+        if (!mDismissSilently && getActivity() instanceof OnPinCheckedListener) {
+            ((OnPinCheckedListener) getActivity()).onPinChecked(
+                    mPinChecked, mRequestType, mRatingString);
         }
+        mDismissSilently = false;
     }
 
     private void handleWrongPin() {
@@ -279,15 +301,14 @@
     }
 
     private void done(String pin) {
-        if (DBG) Log.d(TAG, "done: mType=" + mType + " pin=" + pin + " stored=" + getPin());
+        if (DEBUG) Log.d(TAG, "done: mType=" + mType + " pin=" + pin + " stored=" + getPin());
         switch (mType) {
             case PIN_DIALOG_TYPE_UNLOCK_CHANNEL:
             case PIN_DIALOG_TYPE_UNLOCK_PROGRAM:
             case PIN_DIALOG_TYPE_UNLOCK_DVR:
             case PIN_DIALOG_TYPE_ENTER_PIN:
-                // TODO: Implement limited number of retrials and timeout logic.
                 if (TextUtils.isEmpty(getPin()) || pin.equals(getPin())) {
-                    exit(PIN_DIALOG_RESULT_SUCCESS);
+                    exit(true);
                 } else {
                     resetPinInput();
                     handleWrongPin();
@@ -301,7 +322,7 @@
                 } else {
                     if (pin.equals(mPrevPin)) {
                         setPin(pin);
-                        exit(PIN_DIALOG_RESULT_SUCCESS);
+                        exit(true);
                     } else {
                         if (TextUtils.isEmpty(getPin())) {
                             mTitleView.setText(R.string.pin_enter_create_pin);
@@ -332,7 +353,7 @@
     }
 
     private void setPin(String pin) {
-        if (DBG) Log.d(TAG, "setPin: " + pin);
+        if (DEBUG) Log.d(TAG, "setPin: " + pin);
         mPin = pin;
         mSharedPreferences.edit().putString(TvSettings.PREF_PIN, pin).apply();
     }
@@ -684,4 +705,20 @@
                     : (value > mMaxValue) ? value - interval : value;
         }
     }
+
+    /**
+     * A listener to the result of {@link PinDialogFragment}. Any activity requiring pin code
+     * checking should implement this listener to receive the result.
+     */
+    public interface OnPinCheckedListener {
+        /**
+         * Called when {@link PinDialogFragment} is dismissed.
+         *
+         * @param checked {@code true} if the pin code entered is checked to be correct,
+         *                otherwise {@code false}.
+         * @param type The dialog type regarding to what pin entering is for.
+         * @param rating The target rating to unblock for.
+         */
+        void onPinChecked(boolean checked, int type, String rating);
+    }
 }
diff --git a/src/com/android/tv/dialog/SafeDismissDialogFragment.java b/src/com/android/tv/dialog/SafeDismissDialogFragment.java
index f671a87..e3390b0 100644
--- a/src/com/android/tv/dialog/SafeDismissDialogFragment.java
+++ b/src/com/android/tv/dialog/SafeDismissDialogFragment.java
@@ -17,11 +17,7 @@
 package com.android.tv.dialog;
 
 import android.app.Activity;
-import android.app.Dialog;
 import android.app.DialogFragment;
-import android.content.Context;
-import android.os.Bundle;
-import android.view.KeyEvent;
 
 import com.android.tv.MainActivity;
 import com.android.tv.TvApplication;
@@ -39,11 +35,6 @@
     private Tracker mTracker;
 
     @Override
-    public Dialog onCreateDialog(Bundle savedInstanceState) {
-        return new TvDialog(getActivity(), getTheme());
-    }
-
-    @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
         mAttached = true;
@@ -92,21 +83,4 @@
             super.dismiss();
         }
     }
-
-    protected class TvDialog extends Dialog {
-        public TvDialog(Context context, int theme) {
-            super(context, theme);
-        }
-
-        @Override
-        public boolean onKeyUp(int keyCode, KeyEvent event) {
-            // When a dialog is showing, key events are handled by the dialog instead of
-            // MainActivity. Therefore, unless a key is a global key, it should be handled here.
-            if (mAttached && keyCode == KeyEvent.KEYCODE_SEARCH && mActivity != null) {
-                mActivity.showSearchActivity();
-                return true;
-            }
-            return super.onKeyUp(keyCode, event);
-        }
-    }
 }
diff --git a/src/com/android/tv/dialog/WebDialogFragment.java b/src/com/android/tv/dialog/WebDialogFragment.java
index 75f93bb..171a256 100644
--- a/src/com/android/tv/dialog/WebDialogFragment.java
+++ b/src/com/android/tv/dialog/WebDialogFragment.java
@@ -37,6 +37,7 @@
     private static final String TITLE = "TITLE";
     private static final String TRACKER_LABEL = "TRACKER_LABEL";
 
+    private WebView mWebView;
     private String mTrackerLabel;
 
     /**
@@ -73,13 +74,21 @@
         String title = getArguments().getString(TITLE);
         getDialog().setTitle(title);
 
-        WebView webView = new WebView(getActivity());
-        webView.setWebViewClient(new WebViewClient());
+        mWebView = new WebView(getActivity());
+        mWebView.setWebViewClient(new WebViewClient());
         String url = getArguments().getString(URL);
-        webView.loadUrl(url);
+        mWebView.loadUrl(url);
         Log.d(TAG, "Loading web content from " + url);
 
-        return webView;
+        return mWebView;
+    }
+
+    @Override
+    public void onDestroyView() {
+        super.onDestroyView();
+        if (mWebView != null) {
+            mWebView.destroy();
+        }
     }
 
     @Override
diff --git a/src/com/android/tv/dvr/BaseDvrDataManager.java b/src/com/android/tv/dvr/BaseDvrDataManager.java
index 89661df..a863744 100644
--- a/src/com/android/tv/dvr/BaseDvrDataManager.java
+++ b/src/com/android/tv/dvr/BaseDvrDataManager.java
@@ -26,7 +26,10 @@
 
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.dvr.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.util.Clock;
 
 import java.util.ArrayList;
@@ -318,5 +321,41 @@
     }
 
     @Override
+    public void checkAndRemoveEmptySeriesRecording(long... seriesRecordingIds) {
+        List<SeriesRecording> toRemove = new ArrayList<>();
+        for (long rId : seriesRecordingIds) {
+            SeriesRecording seriesRecording = getSeriesRecording(rId);
+            if (seriesRecording != null && isEmptySeriesRecording(seriesRecording)) {
+                toRemove.add(seriesRecording);
+            }
+        }
+        removeSeriesRecording(SeriesRecording.toArray(toRemove));
+    }
+
+    /**
+     * Returns {@code true}, if the series recording is empty and can be removed. If a series
+     * recording is in NORMAL state or has recordings or schedules, it is not empty and cannot be
+     * removed.
+     */
+    protected final boolean isEmptySeriesRecording(@NonNull SeriesRecording seriesRecording) {
+        if (!seriesRecording.isStopped()) {
+            return false;
+        }
+        long seriesRecordingId = seriesRecording.getId();
+        for (ScheduledRecording r : getAvailableScheduledRecordings()) {
+            if (r.getSeriesRecordingId() == seriesRecordingId) {
+                return false;
+            }
+        }
+        String seriesId = seriesRecording.getSeriesId();
+        for (RecordedProgram r : getRecordedPrograms()) {
+            if (seriesId.equals(r.getSeriesId())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
     public void forgetStorage(String inputId) { }
 }
diff --git a/src/com/android/tv/dvr/DvrDataManager.java b/src/com/android/tv/dvr/DvrDataManager.java
index 0661366..6d400b8 100644
--- a/src/com/android/tv/dvr/DvrDataManager.java
+++ b/src/com/android/tv/dvr/DvrDataManager.java
@@ -21,7 +21,10 @@
 import android.support.annotation.Nullable;
 import android.util.Range;
 
-import com.android.tv.dvr.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.SeriesRecording;
 
 import java.util.Collection;
 import java.util.List;
@@ -211,6 +214,13 @@
     Collection<Long> getDisallowedProgramIds();
 
     /**
+     * Checks each of the give series recordings to see if it's empty, i.e., it doesn't contains
+     * any available schedules or recorded programs, and it's status is
+     * {@link SeriesRecording#STATE_SERIES_STOPPED}; and removes those empty series recordings.
+     */
+    void checkAndRemoveEmptySeriesRecording(long... seriesRecordingIds);
+
+    /**
      * Listens for the DVR schedules loading finished.
      */
     interface OnDvrScheduleLoadFinishedListener {
diff --git a/src/com/android/tv/dvr/DvrDataManagerImpl.java b/src/com/android/tv/dvr/DvrDataManagerImpl.java
index 46682a4..6094ca7 100644
--- a/src/com/android/tv/dvr/DvrDataManagerImpl.java
+++ b/src/com/android/tv/dvr/DvrDataManagerImpl.java
@@ -42,7 +42,11 @@
 import com.android.tv.TvApplication;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.dvr.DvrStorageStatusManager.OnStorageMountChangedListener;
-import com.android.tv.dvr.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.IdGenerator;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.dvr.provider.AsyncDvrDbTask.AsyncAddScheduleTask;
 import com.android.tv.dvr.provider.AsyncDvrDbTask.AsyncAddSeriesRecordingTask;
 import com.android.tv.dvr.provider.AsyncDvrDbTask.AsyncDeleteScheduleTask;
@@ -51,12 +55,14 @@
 import com.android.tv.dvr.provider.AsyncDvrDbTask.AsyncDvrQuerySeriesRecordingTask;
 import com.android.tv.dvr.provider.AsyncDvrDbTask.AsyncUpdateScheduleTask;
 import com.android.tv.dvr.provider.AsyncDvrDbTask.AsyncUpdateSeriesRecordingTask;
+import com.android.tv.dvr.provider.DvrDbSync;
+import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
 import com.android.tv.util.AsyncDbTask;
 import com.android.tv.util.AsyncDbTask.AsyncRecordedProgramQueryTask;
 import com.android.tv.util.Clock;
 import com.android.tv.util.Filter;
 import com.android.tv.util.TvInputManagerHelper;
-import com.android.tv.util.TvProviderUriMatcher;
+import com.android.tv.util.TvUriMatcher;
 import com.android.tv.util.Utils;
 
 import java.util.ArrayList;
@@ -267,11 +273,14 @@
                     removeScheduledRecording(ScheduledRecording.toArray(toDelete));
                 }
                 IdGenerator.SCHEDULED_RECORDING.setMaxId(maxId);
+                if (mRecordedProgramLoadFinished) {
+                    validateSeriesRecordings();
+                }
                 mDvrLoadFinished = true;
                 notifyDvrScheduleLoadFinished();
-                mDbSync = new DvrDbSync(mContext, DvrDataManagerImpl.this);
-                mDbSync.start();
                 if (isInitialized()) {
+                    mDbSync = new DvrDbSync(mContext, DvrDataManagerImpl.this);
+                    mDbSync.start();
                     SeriesRecordingScheduler.getInstance(mContext).start();
                 }
             }
@@ -306,8 +315,11 @@
         if (uri == null) {
             uri = RecordedPrograms.CONTENT_URI;
         }
-        int match = TvProviderUriMatcher.match(uri);
-        if (match == TvProviderUriMatcher.MATCH_RECORDED_PROGRAM) {
+        if (recordedPrograms == null) {
+            recordedPrograms = Collections.emptyList();
+        }
+        int match = TvUriMatcher.match(uri);
+        if (match == TvUriMatcher.MATCH_RECORDED_PROGRAM) {
             if (!mRecordedProgramLoadFinished) {
                 for (RecordedProgram recorded : recordedPrograms) {
                     if (isInputAvailable(recorded.getInputId())) {
@@ -318,7 +330,11 @@
                 }
                 mRecordedProgramLoadFinished = true;
                 notifyRecordedProgramLoadFinished();
-            } else if (recordedPrograms == null || recordedPrograms.isEmpty()) {
+                if (isInitialized()) {
+                    mDbSync = new DvrDbSync(mContext, DvrDataManagerImpl.this);
+                    mDbSync.start();
+                }
+            } else if (recordedPrograms.isEmpty()) {
                 List<RecordedProgram> oldRecordedPrograms =
                         new ArrayList<>(mRecordedPrograms.values());
                 mRecordedPrograms.clear();
@@ -355,19 +371,24 @@
                 }
             }
             if (isInitialized()) {
+                validateSeriesRecordings();
                 SeriesRecordingScheduler.getInstance(mContext).start();
             }
-        } else if (match == TvProviderUriMatcher.MATCH_RECORDED_PROGRAM_ID) {
+        } else if (match == TvUriMatcher.MATCH_RECORDED_PROGRAM_ID) {
             if (!mRecordedProgramLoadFinished) {
                 return;
             }
             long id = ContentUris.parseId(uri);
             if (DEBUG) Log.d(TAG, "changed recorded program #" + id + " to " + recordedPrograms);
-            if (recordedPrograms == null || recordedPrograms.isEmpty()) {
+            if (recordedPrograms.isEmpty()) {
                 mRecordedProgramsForRemovedInput.remove(id);
                 RecordedProgram old = mRecordedPrograms.remove(id);
                 if (old != null) {
                     notifyRecordedProgramsRemoved(old);
+                    SeriesRecording r = mSeriesId2SeriesRecordings.get(old.getSeriesId());
+                    if (r != null && isEmptySeriesRecording(r)) {
+                        removeSeriesRecording(r);
+                    }
                 }
             } else {
                 RecordedProgram recordedProgram = recordedPrograms.get(0);
@@ -592,10 +613,16 @@
     public void removeScheduledRecording(boolean forceRemove, ScheduledRecording... schedules) {
         List<ScheduledRecording> schedulesToDelete = new ArrayList<>();
         List<ScheduledRecording> schedulesNotToDelete = new ArrayList<>();
+        Set<Long> seriesRecordingIdsToCheck = new HashSet<>();
         for (ScheduledRecording r : schedules) {
             mScheduledRecordings.remove(r.getId());
-            getDeletedScheduleMap().remove(r.getId());
+            getDeletedScheduleMap().remove(r.getProgramId());
             mProgramId2ScheduledRecordings.remove(r.getProgramId());
+            if (r.getSeriesRecordingId() != SeriesRecording.ID_NOT_SET
+                    && (r.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
+                    || r.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
+                seriesRecordingIdsToCheck.add(r.getSeriesRecordingId());
+            }
             boolean isScheduleForRemovedInput =
                     mScheduledRecordingsForRemovedInput.remove(r.getProgramId()) != null;
             // If it belongs to the series recording and it's not started yet, just mark delete
@@ -614,8 +641,19 @@
             }
         }
         if (mDvrLoadFinished) {
+            if (mRecordedProgramLoadFinished) {
+                checkAndRemoveEmptySeriesRecording(seriesRecordingIdsToCheck);
+            }
             notifyScheduledRecordingRemoved(schedules);
         }
+        Iterator<ScheduledRecording> iterator = schedulesNotToDelete.iterator();
+        while (iterator.hasNext()) {
+            ScheduledRecording r = iterator.next();
+            if (!mSeriesRecordings.containsKey(r.getSeriesRecordingId())) {
+                iterator.remove();
+                schedulesToDelete.add(r);
+            }
+        }
         if (!schedulesToDelete.isEmpty()) {
             new AsyncDeleteScheduleTask(mContext).executeOnDbThread(
                     ScheduledRecording.toArray(schedulesToDelete));
@@ -669,6 +707,7 @@
 
     private void updateScheduledRecording(boolean updateDb, final ScheduledRecording... schedules) {
         List<ScheduledRecording> toUpdate = new ArrayList<>();
+        Set<Long> seriesRecordingIdsToCheck = new HashSet<>();
         for (ScheduledRecording r : schedules) {
             if (!SoftPreconditions.checkState(mScheduledRecordings.containsKey(r.getId()), TAG,
                     "Recording not found for: " + r)) {
@@ -691,6 +730,13 @@
             if (programId != ScheduledRecording.ID_NOT_SET) {
                 mProgramId2ScheduledRecordings.put(programId, r);
             }
+            if (r.getState() == ScheduledRecording.STATE_RECORDING_FAILED
+                    && r.getSeriesRecordingId() != SeriesRecording.ID_NOT_SET) {
+                // If the scheduled recording is failed, it may cause the automatically generated
+                // series recording for this schedule becomes invalid (with no future schedules and
+                // past recordings.) We should check and remove these series recordings.
+                seriesRecordingIdsToCheck.add(r.getSeriesRecordingId());
+            }
         }
         if (toUpdate.isEmpty()) {
             return;
@@ -702,12 +748,17 @@
         if (updateDb) {
             new AsyncUpdateScheduleTask(mContext).executeOnDbThread(scheduleArray);
         }
+        checkAndRemoveEmptySeriesRecording(seriesRecordingIdsToCheck);
         removeDeletedSchedules(schedules);
     }
 
     @Override
     public void updateSeriesRecording(final SeriesRecording... seriesRecordings) {
         for (SeriesRecording r : seriesRecordings) {
+            if (!SoftPreconditions.checkArgument(mSeriesRecordings.containsKey(r.getId()), TAG,
+                    "Non Existing Series ID: " + r)) {
+                continue;
+            }
             SeriesRecording old1 = mSeriesRecordings.put(r.getId(), r);
             SeriesRecording old2 = mSeriesId2SeriesRecordings.put(r.getSeriesId(), r);
             SoftPreconditions.checkArgument(old1.equals(old2), TAG, "Series ID cannot be"
@@ -769,14 +820,6 @@
                                 return r.getInputId().equals(inputId);
                             }
                         });
-        List<SeriesRecording> movedSeriesRecordings =
-                moveElements(mSeriesRecordingsForRemovedInput, mSeriesRecordings,
-                        new Filter<SeriesRecording>() {
-                            @Override
-                            public boolean filter(SeriesRecording r) {
-                                return r.getInputId().equals(inputId);
-                            }
-                        });
         List<RecordedProgram> movedRecordedPrograms =
                 moveElements(mRecordedProgramsForRemovedInput, mRecordedPrograms,
                         new Filter<RecordedProgram>() {
@@ -785,6 +828,21 @@
                                 return r.getInputId().equals(inputId);
                             }
                         });
+        List<SeriesRecording> removedSeriesRecordings = new ArrayList<>();
+        List<SeriesRecording> movedSeriesRecordings =
+                moveElements(mSeriesRecordingsForRemovedInput, mSeriesRecordings,
+                        new Filter<SeriesRecording>() {
+                            @Override
+                            public boolean filter(SeriesRecording r) {
+                                if (r.getInputId().equals(inputId)) {
+                                    if (!isEmptySeriesRecording(r)) {
+                                        return true;
+                                    }
+                                    removedSeriesRecordings.add(r);
+                                }
+                                return false;
+                            }
+                        });
         if (!movedSchedules.isEmpty()) {
             for (ScheduledRecording schedule : movedSchedules) {
                 mProgramId2ScheduledRecordings.put(schedule.getProgramId(), schedule);
@@ -795,6 +853,11 @@
                 mSeriesId2SeriesRecordings.put(seriesRecording.getSeriesId(), seriesRecording);
             }
         }
+        for (SeriesRecording r : removedSeriesRecordings) {
+            mSeriesRecordingsForRemovedInput.remove(r.getId());
+        }
+        new AsyncDeleteSeriesRecordingTask(mContext).executeOnDbThread(
+                SeriesRecording.toArray(removedSeriesRecordings));
         // Notify after all the data are moved.
         if (!movedSchedules.isEmpty()) {
             notifyScheduledRecordingAdded(ScheduledRecording.toArray(movedSchedules));
@@ -811,20 +874,20 @@
         if (DEBUG) Log.d(TAG, "hideInput " + inputId);
         List<ScheduledRecording> movedSchedules =
                 moveElements(mScheduledRecordings, mScheduledRecordingsForRemovedInput,
-                    new Filter<ScheduledRecording>() {
-                        @Override
-                        public boolean filter(ScheduledRecording r) {
-                            return r.getInputId().equals(inputId);
-                        }
-                    });
+                        new Filter<ScheduledRecording>() {
+                            @Override
+                            public boolean filter(ScheduledRecording r) {
+                                return r.getInputId().equals(inputId);
+                            }
+                        });
         List<SeriesRecording> movedSeriesRecordings =
                 moveElements(mSeriesRecordings, mSeriesRecordingsForRemovedInput,
-                    new Filter<SeriesRecording>() {
-                        @Override
-                        public boolean filter(SeriesRecording r) {
-                            return r.getInputId().equals(inputId);
-                        }
-                    });
+                        new Filter<SeriesRecording>() {
+                            @Override
+                            public boolean filter(SeriesRecording r) {
+                                return r.getInputId().equals(inputId);
+                            }
+                        });
         List<RecordedProgram> movedRecordedPrograms =
                 moveElements(mRecordedPrograms, mRecordedProgramsForRemovedInput,
                         new Filter<RecordedProgram>() {
@@ -855,6 +918,15 @@
         }
     }
 
+    private void checkAndRemoveEmptySeriesRecording(Set<Long> seriesRecordingIds) {
+        int i = 0;
+        long[] rIds = new long[seriesRecordingIds.size()];
+        for (long rId : seriesRecordingIds) {
+            rIds[i++] = rId;
+        }
+        checkAndRemoveEmptySeriesRecording(rIds);
+    }
+
     @Override
     public void forgetStorage(String inputId) {
         List<ScheduledRecording> schedulesToDelete = new ArrayList<>();
@@ -901,6 +973,25 @@
         }.executeOnDbThread();
     }
 
+    private void validateSeriesRecordings() {
+        Iterator<SeriesRecording> iter = mSeriesRecordings.values().iterator();
+        List<SeriesRecording> removedSeriesRecordings = new ArrayList<>();
+        while (iter.hasNext()) {
+            SeriesRecording r = iter.next();
+            if (isEmptySeriesRecording(r)) {
+                iter.remove();
+                removedSeriesRecordings.add(r);
+            }
+        }
+        if (!removedSeriesRecordings.isEmpty()) {
+            SeriesRecording[] removed = SeriesRecording.toArray(removedSeriesRecordings);
+            new AsyncDeleteSeriesRecordingTask(mContext).executeOnDbThread(removed);
+            if (mDvrLoadFinished) {
+                notifySeriesRecordingRemoved(removed);
+            }
+        }
+    }
+
     private final class RecordedProgramsQueryTask extends AsyncRecordedProgramQueryTask {
         private final Uri mUri;
 
diff --git a/src/com/android/tv/dvr/DvrManager.java b/src/com/android/tv/dvr/DvrManager.java
index 5fa6f90..d222003 100644
--- a/src/com/android/tv/dvr/DvrManager.java
+++ b/src/com/android/tv/dvr/DvrManager.java
@@ -46,7 +46,9 @@
 import com.android.tv.dvr.DvrDataManager.OnRecordedProgramLoadFinishedListener;
 import com.android.tv.dvr.DvrDataManager.RecordedProgramListener;
 import com.android.tv.dvr.DvrScheduleManager.OnInitializeListener;
-import com.android.tv.dvr.SeriesRecording.SeriesState;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.util.AsyncDbTask;
 import com.android.tv.util.Utils;
 
@@ -142,7 +144,7 @@
     }
 
     private void createSeriesRecordingForRecordedProgramIfNeeded(RecordedProgram recordedProgram) {
-        if (recordedProgram.getSeriesId() != null) {
+        if (recordedProgram.isEpisodic()) {
             SeriesRecording seriesRecording =
                     mDataManager.getSeriesRecording(recordedProgram.getSeriesId());
             if (seriesRecording == null) {
@@ -234,7 +236,7 @@
      * Adds a new series recording and schedules for the programs with the initial state.
      */
     public SeriesRecording addSeriesRecording(Program selectedProgram,
-            List<Program> programsToSchedule, @SeriesState int initialState) {
+            List<Program> programsToSchedule, @SeriesRecording.SeriesState int initialState) {
         Log.i(TAG, "Adding series recording for program " + selectedProgram + ", and schedules: "
                 + programsToSchedule);
         if (!SoftPreconditions.checkState(mDataManager.isInitialized())) {
@@ -308,8 +310,7 @@
             ScheduledRecording scheduleWithSameProgram =
                     mDataManager.getScheduledRecordingForProgramId(program.getId());
             if (scheduleWithSameProgram != null) {
-                if (scheduleWithSameProgram.getState()
-                        == ScheduledRecording.STATE_RECORDING_NOT_STARTED) {
+                if (scheduleWithSameProgram.isNotStarted()) {
                     ScheduledRecording r = ScheduledRecording.buildFrom(scheduleWithSameProgram)
                             .setSeriesRecordingId(series.getId())
                             .build();
@@ -337,10 +338,10 @@
      */
     public void updateSeriesRecording(SeriesRecording series) {
         if (SoftPreconditions.checkState(mDataManager.isDvrScheduleLoadFinished())) {
-            SeriesRecordingScheduler scheduler = SeriesRecordingScheduler.getInstance(mAppContext);
-            scheduler.pauseUpdate();
             SeriesRecording previousSeries = mDataManager.getSeriesRecording(series.getId());
             if (previousSeries != null) {
+                // If the channel option of series changed, remove the existing schedules. The new
+                // schedules will be added by SeriesRecordingScheduler or by SeriesSettingsFragment.
                 if (previousSeries.getChannelOption() != series.getChannelOption()
                         || (previousSeries.getChannelOption() == SeriesRecording.OPTION_CHANNEL_ONE
                         && previousSeries.getChannelId() != series.getChannelId())) {
@@ -350,6 +351,18 @@
                     for (ScheduledRecording schedule : schedules) {
                         if (schedule.isNotStarted()) {
                             schedulesToRemove.add(schedule);
+                        } else if (schedule.isInProgress()
+                                && series.getChannelOption() == SeriesRecording.OPTION_CHANNEL_ONE
+                                && schedule.getChannelId() != series.getChannelId()) {
+                            stopRecording(schedule);
+                        }
+                    }
+                    List<ScheduledRecording> deletedSchedules =
+                            new ArrayList<>(mDataManager.getDeletedSchedules());
+                    for (ScheduledRecording deletedSchedule : deletedSchedules) {
+                        if (deletedSchedule.getSeriesRecordingId() == series.getId()
+                                && deletedSchedule.getEndTimeMs() > System.currentTimeMillis()) {
+                            schedulesToRemove.add(deletedSchedule);
                         }
                     }
                     mDataManager.removeScheduledRecording(true,
@@ -363,7 +376,7 @@
                 List<ScheduledRecording> schedulesToUpdate = new ArrayList<>();
                 for (ScheduledRecording schedule
                         : mDataManager.getScheduledRecordings(series.getId())) {
-                    if (schedule.isNotStarted()) {
+                    if (schedule.isNotStarted() || schedule.isInProgress()) {
                         schedulesToUpdate.add(ScheduledRecording.buildFrom(schedule)
                                 .setPriority(priority).build());
                     }
@@ -373,7 +386,6 @@
                             ScheduledRecording.toArray(schedulesToUpdate));
                 }
             }
-            scheduler.resumeUpdate();
         }
     }
 
@@ -400,33 +412,6 @@
     }
 
     /**
-     * Returns true, if the series recording can be removed. If a series recording is NORMAL state
-     * or has recordings or schedules, it cannot be removed.
-     */
-    public boolean canRemoveSeriesRecording(long seriesRecordingId) {
-        SeriesRecording seriesRecording = mDataManager.getSeriesRecording(seriesRecordingId);
-        if (seriesRecording == null) {
-            return false;
-        }
-        if (!seriesRecording.isStopped()) {
-            return false;
-        }
-        for (ScheduledRecording r : mDataManager.getAvailableScheduledRecordings()) {
-            if (r.getSeriesRecordingId() == seriesRecordingId) {
-                return false;
-            }
-        }
-        String seriesId = seriesRecording.getSeriesId();
-        SoftPreconditions.checkNotNull(seriesId);
-        for (RecordedProgram r : mDataManager.getRecordedPrograms()) {
-            if (seriesId.equals(r.getSeriesId())) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
      * Stops the currently recorded program
      */
     public void stopRecording(final ScheduledRecording recording) {
@@ -509,13 +494,16 @@
         if (!SoftPreconditions.checkState(mDataManager.isInitialized())) {
             return;
         }
-        new AsyncDbTask<Void, Void, Void>() {
+        new AsyncDbTask<Void, Void, Integer>() {
             @Override
-            protected Void doInBackground(Void... params) {
+            protected Integer doInBackground(Void... params) {
                 ContentResolver resolver = mAppContext.getContentResolver();
-                int deletedCounts = resolver.delete(recordedProgram.getUri(), null, null);
+                return resolver.delete(recordedProgram.getUri(), null, null);
+            }
+
+            @Override
+            protected void onPostExecute(Integer deletedCounts) {
                 if (deletedCounts > 0) {
-                    // TODO: executeOnExecutor should be called on the main thread.
                     new AsyncTask<Void, Void, Void>() {
                         @Override
                         protected Void doInBackground(Void... params) {
@@ -524,7 +512,6 @@
                         }
                     }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
                 }
-                return null;
             }
         }.executeOnDbThread();
     }
@@ -539,13 +526,22 @@
                 dbOperations.add(ContentProviderOperation.newDelete(r.getUri()).build());
             }
         }
-        new AsyncDbTask<Void, Void, Void>() {
+        new AsyncDbTask<Void, Void, Boolean>() {
             @Override
-            protected Void doInBackground(Void... params) {
+            protected Boolean doInBackground(Void... params) {
                 ContentResolver resolver = mAppContext.getContentResolver();
                 try {
                     resolver.applyBatch(TvContract.AUTHORITY, dbOperations);
-                    // TODO: executeOnExecutor should be called on the main thread.
+                } catch (RemoteException | OperationApplicationException e) {
+                    Log.w(TAG, "Remove recorded programs from DB failed.", e);
+                    return false;
+                }
+                return true;
+            }
+
+            @Override
+            protected void onPostExecute(Boolean success) {
+                if (success) {
                     new AsyncTask<Void, Void, Void>() {
                         @Override
                         protected Void doInBackground(Void... params) {
@@ -555,10 +551,7 @@
                             return null;
                         }
                     }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-                } catch (RemoteException | OperationApplicationException e) {
-                    Log.w(TAG, "Remove reocrded programs from DB failed.", e);
                 }
-                return null;
             }
         }.executeOnDbThread();
     }
@@ -657,6 +650,9 @@
         if (!mDataManager.isDvrScheduleLoadFinished() || channel == null) {
             return false;
         }
+        if (channel.isRecordingProhibited()) {
+            return false;
+        }
         TvInputInfo info = Utils.getTvInputInfoForChannelId(mAppContext, channel.getId());
         if (info == null) {
             Log.w(TAG, "Could not find TvInputInfo for " + channel);
@@ -680,7 +676,12 @@
         if (!mDataManager.isInitialized()) {
             return false;
         }
-        TvInputInfo info = Utils.getTvInputInfoForProgram(mAppContext, program);
+        Channel channel = TvApplication.getSingletons(mAppContext).getChannelDataManager()
+                .getChannel(program.getChannelId());
+        if (channel == null || channel.isRecordingProhibited()) {
+            return false;
+        }
+        TvInputInfo info = Utils.getTvInputInfoForChannelId(mAppContext, channel.getId());
         if (info == null) {
             Log.w(TAG, "Could not find TvInputInfo for " + program);
             return false;
@@ -733,6 +734,17 @@
         return mDataManager.getSeriesRecording(program.getSeriesId());
     }
 
+    /**
+     * Returns if there are valid items. Valid item contains {@link RecordedProgram},
+     * available {@link ScheduledRecording} and {@link SeriesRecording}.
+     */
+    public boolean hasValidItems() {
+        return !(mDataManager.getRecordedPrograms().isEmpty()
+                && mDataManager.getStartedRecordings().isEmpty()
+                && mDataManager.getNonStartedScheduledRecordings().isEmpty()
+                && mDataManager.getSeriesRecordings().isEmpty());
+    }
+
     @WorkerThread
     @VisibleForTesting
     // Should be public to use mock DvrManager object.
@@ -840,9 +852,10 @@
     }
 
     /**
-     * Listener internally used inside dvr package.
+     * Listener to stop recording request. Should only be internally used inside dvr and its
+     * sub-package.
      */
-    interface Listener {
+    public interface Listener {
         void onStopRecordingRequested(ScheduledRecording scheduledRecording);
     }
 }
diff --git a/src/com/android/tv/dvr/DvrRecordingService.java b/src/com/android/tv/dvr/DvrRecordingService.java
deleted file mode 100644
index 8c40aaa..0000000
--- a/src/com/android/tv/dvr/DvrRecordingService.java
+++ /dev/null
@@ -1,122 +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.dvr;
-
-import android.app.AlarmManager;
-import android.app.Service;
-import android.content.Context;
-import android.content.Intent;
-import android.os.HandlerThread;
-import android.os.IBinder;
-import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
-import android.util.Log;
-
-import com.android.tv.ApplicationSingletons;
-import com.android.tv.TvApplication;
-import com.android.tv.common.SoftPreconditions;
-import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.util.Clock;
-import com.android.tv.util.RecurringRunner;
-
-/**
- * DVR Scheduler service.
- *
- * <p> This service is responsible for:
- * <ul>
- *     <li>Send record commands to TV inputs</li>
- *     <li>Wake up at proper timing for recording</li>
- *     <li>Deconflict schedule, handling overlapping times etc.</li>
- *     <li>
- *
- * </ul>
- *
- * <p>The service does not stop it self.
- */
-public class DvrRecordingService extends Service {
-    private static final String TAG = "DvrRecordingService";
-    private static final boolean DEBUG = false;
-    public static final String HANDLER_THREAD_NAME = "DvrRecordingService-handler";
-
-    public static void startService(Context context) {
-        Intent dvrSchedulerIntent = new Intent(context, DvrRecordingService.class);
-        context.startService(dvrSchedulerIntent);
-    }
-
-    private final Clock mClock = Clock.SYSTEM;
-    private RecurringRunner mReaperRunner;
-
-    private Scheduler mScheduler;
-    private HandlerThread mHandlerThread;
-
-    @Override
-    public void onCreate() {
-        TvApplication.setCurrentRunningProcess(this, true);
-        if (DEBUG) Log.d(TAG, "onCreate");
-        super.onCreate();
-        SoftPreconditions.checkFeatureEnabled(this, CommonFeatures.DVR, TAG);
-        ApplicationSingletons singletons = TvApplication.getSingletons(this);
-        WritableDvrDataManager dataManager = (WritableDvrDataManager) singletons.getDvrDataManager();
-
-        AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
-        // mScheduler may have been set for testing.
-        if (mScheduler == null) {
-            mHandlerThread = new HandlerThread(HANDLER_THREAD_NAME);
-            mHandlerThread.start();
-            mScheduler = new Scheduler(mHandlerThread.getLooper(), singletons.getDvrManager(),
-                    singletons.getInputSessionManager(), dataManager,
-                    singletons.getChannelDataManager(), singletons.getTvInputManagerHelper(), this,
-                    mClock, alarmManager);
-            mScheduler.start();
-        }
-        mReaperRunner = new RecurringRunner(this, java.util.concurrent.TimeUnit.DAYS.toMillis(1),
-                new ScheduledProgramReaper(dataManager, mClock), null);
-        mReaperRunner.start();
-    }
-
-    @Override
-    public int onStartCommand(Intent intent, int flags, int startId) {
-        if (DEBUG) Log.d(TAG, "onStartCommand (" + intent + "," + flags + "," + startId + ")");
-        mScheduler.update();
-        return START_STICKY;
-    }
-
-    @Override
-    public void onDestroy() {
-        if (DEBUG) Log.d(TAG, "onDestroy");
-        mReaperRunner.stop();
-        mScheduler.stop();
-        mScheduler = null;
-        if (mHandlerThread != null) {
-            mHandlerThread.quitSafely();
-            mHandlerThread = null;
-        }
-        super.onDestroy();
-    }
-
-    @Nullable
-    @Override
-    public IBinder onBind(Intent intent) {
-        return null;
-    }
-
-    @VisibleForTesting
-    void setScheduler(Scheduler scheduler) {
-        Log.i(TAG, "Setting scheduler for tests to " + scheduler);
-        mScheduler = scheduler;
-    }
-}
diff --git a/src/com/android/tv/dvr/DvrScheduleManager.java b/src/com/android/tv/dvr/DvrScheduleManager.java
index a5851a7..b72117a 100644
--- a/src/com/android/tv/dvr/DvrScheduleManager.java
+++ b/src/com/android/tv/dvr/DvrScheduleManager.java
@@ -24,7 +24,6 @@
 import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
 import android.util.ArraySet;
-import android.util.LongSparseArray;
 import android.util.Range;
 
 import com.android.tv.ApplicationSingletons;
@@ -35,7 +34,10 @@
 import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
+import com.android.tv.dvr.recorder.InputTaskScheduler;
 import com.android.tv.util.CompositeComparator;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.util.Utils;
 
 import java.util.ArrayList;
@@ -88,9 +90,8 @@
     private final Map<String, List<ScheduledRecording>> mInputScheduleMap = new HashMap<>();
     // The inner map is a hash map from scheduled recording to its conflicting status, i.e.,
     // the boolean value true denotes the schedule is just partially conflicting, which means
-    // although there's conflictit, it might still be recorded partially.
-    private final Map<String, Map<ScheduledRecording, Boolean>> mInputConflictInfoMap =
-            new HashMap<>();
+    // although there's conflict, it might still be recorded partially.
+    private final Map<String, Map<Long, ConflictInfo>> mInputConflictInfoMap = new HashMap<>();
 
     private boolean mInitialized;
 
@@ -171,10 +172,9 @@
                             mInputScheduleMap.remove(inputId);
                         }
                     }
-                    Map<ScheduledRecording, Boolean> conflictInfo =
-                            mInputConflictInfoMap.get(inputId);
+                    Map<Long, ConflictInfo> conflictInfo = mInputConflictInfoMap.get(inputId);
                     if (conflictInfo != null) {
-                        conflictInfo.remove(schedule);
+                        conflictInfo.remove(schedule.getId());
                         if (conflictInfo.isEmpty()) {
                             mInputConflictInfoMap.remove(inputId);
                         }
@@ -221,21 +221,11 @@
                         mInputScheduleMap.remove(inputId);
                     }
                     // Update conflict list as well
-                    Map<ScheduledRecording, Boolean> conflictInfo =
-                            mInputConflictInfoMap.get(inputId);
+                    Map<Long, ConflictInfo> conflictInfo = mInputConflictInfoMap.get(inputId);
                     if (conflictInfo != null) {
-                        // Compare ID because ScheduledRecording.equals() doesn't work if the state
-                        // is changed.
-                        ScheduledRecording oldSchedule = null;
-                        for (ScheduledRecording s : conflictInfo.keySet()) {
-                            if (s.getId() == schedule.getId()) {
-                                oldSchedule = s;
-                                break;
-                            }
-                        }
-                        if (oldSchedule != null) {
-                            conflictInfo.put(schedule, conflictInfo.get(oldSchedule));
-                            conflictInfo.remove(oldSchedule);
+                        ConflictInfo oldConflictInfo = conflictInfo.get(schedule.getId());
+                        if (oldConflictInfo != null) {
+                            oldConflictInfo.schedule = schedule;
                         }
                     }
                 }
@@ -317,24 +307,25 @@
         List<ScheduledRecording> addedConflicts = new ArrayList<>();
         List<ScheduledRecording> removedConflicts = new ArrayList<>();
         for (String inputId : mInputScheduleMap.keySet()) {
-            Map<ScheduledRecording, Boolean> oldConflictsInfo = mInputConflictInfoMap.get(inputId);
+            Map<Long, ConflictInfo> oldConflictInfo = mInputConflictInfoMap.get(inputId);
             Map<Long, ScheduledRecording> oldConflictMap = new HashMap<>();
-            if (oldConflictsInfo != null) {
-                for (ScheduledRecording r : oldConflictsInfo.keySet()) {
-                    oldConflictMap.put(r.getId(), r);
+            if (oldConflictInfo != null) {
+                for (ConflictInfo conflictInfo : oldConflictInfo.values()) {
+                    oldConflictMap.put(conflictInfo.schedule.getId(), conflictInfo.schedule);
                 }
             }
-            Map<ScheduledRecording, Boolean> conflictInfo = getConflictingSchedulesInfo(inputId);
-            if (conflictInfo.isEmpty()) {
+            List<ConflictInfo> conflicts = getConflictingSchedulesInfo(inputId);
+            if (conflicts.isEmpty()) {
                 mInputConflictInfoMap.remove(inputId);
             } else {
-                mInputConflictInfoMap.put(inputId, conflictInfo);
-                List<ScheduledRecording> conflicts = new ArrayList<>(conflictInfo.keySet());
-                for (ScheduledRecording r : conflicts) {
-                    if (oldConflictMap.remove(r.getId()) == null) {
-                        addedConflicts.add(r);
+                Map<Long, ConflictInfo> conflictInfos = new HashMap<>();
+                for (ConflictInfo conflictInfo : conflicts) {
+                    conflictInfos.put(conflictInfo.schedule.getId(), conflictInfo);
+                    if (oldConflictMap.remove(conflictInfo.schedule.getId()) == null) {
+                        addedConflicts.add(conflictInfo.schedule);
                     }
                 }
+                mInputConflictInfoMap.put(inputId, conflictInfos);
             }
             removedConflicts.addAll(oldConflictMap.values());
         }
@@ -565,8 +556,7 @@
     }
 
     /**
-     * Returns list of all conflicting scheduled recordings with schedules belonging to {@code
-     * seriesRecording}
+     * Returns list of all conflicting scheduled recordings for the given {@code seriesRecording}
      * recording.
      * <p>
      * Any empty list means there is no conflicts.
@@ -581,9 +571,18 @@
         if (input == null || !input.canRecord() || input.getTunerCount() <= 0) {
             return Collections.emptyList();
         }
-        List<ScheduledRecording> schedulesForSeries = mDataManager.getScheduledRecordings(
+        List<ScheduledRecording> scheduledRecordingForSeries = mDataManager.getScheduledRecordings(
                 seriesRecording.getId());
-        return getConflictingSchedules(input, schedulesForSeries);
+        List<ScheduledRecording> availableScheduledRecordingForSeries = new ArrayList<>();
+        for (ScheduledRecording scheduledRecording : scheduledRecordingForSeries) {
+            if (scheduledRecording.isNotStarted() || scheduledRecording.isInProgress()) {
+                availableScheduledRecordingForSeries.add(scheduledRecording);
+            }
+        }
+        if (availableScheduledRecordingForSeries.isEmpty()) {
+            return Collections.emptyList();
+        }
+        return getConflictingSchedules(input, availableScheduledRecordingForSeries);
     }
 
     /**
@@ -617,16 +616,16 @@
      * the given input.
      */
     @NonNull
-    private Map<ScheduledRecording, Boolean> getConflictingSchedulesInfo(String inputId) {
+    private List<ConflictInfo> getConflictingSchedulesInfo(String inputId) {
         SoftPreconditions.checkState(mInitialized, TAG, "Not initialized yet");
         TvInputInfo input = Utils.getTvInputInfoForInputId(mContext, inputId);
         SoftPreconditions.checkState(input != null, TAG, "Can't find input for : " + inputId);
         if (!mInitialized || input == null) {
-            return Collections.emptyMap();
+            return Collections.emptyList();
         }
         List<ScheduledRecording> schedules = mInputScheduleMap.get(input.getId());
         if (schedules == null || schedules.isEmpty()) {
-            return Collections.emptyMap();
+            return Collections.emptyList();
         }
         return getConflictingSchedulesInfo(schedules, input.getTunerCount());
     }
@@ -645,8 +644,8 @@
         if (!mInitialized || input == null) {
             return false;
         }
-        Map<ScheduledRecording, Boolean> conflicts = mInputConflictInfoMap.get(input.getId());
-        return conflicts != null && conflicts.containsKey(schedule);
+        Map<Long, ConflictInfo> conflicts = mInputConflictInfoMap.get(input.getId());
+        return conflicts != null && conflicts.containsKey(schedule.getId());
     }
 
     /**
@@ -664,8 +663,12 @@
         if (!mInitialized || input == null) {
             return false;
         }
-        Map<ScheduledRecording, Boolean> conflicts = mInputConflictInfoMap.get(input.getId());
-        return conflicts != null && conflicts.getOrDefault(schedule, false);
+        Map<Long, ConflictInfo> conflicts = mInputConflictInfoMap.get(input.getId());
+        if (conflicts != null) {
+            ConflictInfo conflictInfo = conflicts.get(schedule.getId());
+            return conflictInfo != null && conflictInfo.partialConflict;
+        }
+        return false;
     }
 
     /**
@@ -813,15 +816,17 @@
     @VisibleForTesting
     static List<ScheduledRecording> getConflictingSchedules(
             List<ScheduledRecording> schedules, int tunerCount, List<Range<Long>> periods) {
-        List<ScheduledRecording> result = new ArrayList<>(
-                getConflictingSchedulesInfo(schedules, tunerCount, periods).keySet());
-        Collections.sort(result, RESULT_COMPARATOR);
+        List<ScheduledRecording> result = new ArrayList<>();
+        for (ConflictInfo conflictInfo :
+                getConflictingSchedulesInfo(schedules, tunerCount, periods)) {
+            result.add(conflictInfo.schedule);
+        }
         return result;
     }
 
     @VisibleForTesting
-    static Map<ScheduledRecording, Boolean> getConflictingSchedulesInfo(
-            List<ScheduledRecording> schedules, int tunerCount) {
+    static List<ConflictInfo> getConflictingSchedulesInfo(List<ScheduledRecording> schedules,
+            int tunerCount) {
         return getConflictingSchedulesInfo(schedules, tunerCount, null);
     }
 
@@ -836,13 +841,13 @@
      *         to be partially recorded under the given schedules and tuner count {@code true},
      *         or not {@code false}.
      */
-    private static Map<ScheduledRecording, Boolean> getConflictingSchedulesInfo(
+    private static List<ConflictInfo> getConflictingSchedulesInfo(
             List<ScheduledRecording> schedules, int tunerCount, List<Range<Long>> periods) {
         List<ScheduledRecording> schedulesToCheck = new ArrayList<>(schedules);
         // Sort by the same order as that in InputTaskScheduler.
         Collections.sort(schedulesToCheck, InputTaskScheduler.getRecordingOrderComparator());
         List<ScheduledRecording> recordings = new ArrayList<>();
-        Map<ScheduledRecording, Boolean> conflicts = new HashMap<>();
+        Map<ScheduledRecording, ConflictInfo> conflicts = new HashMap<>();
         Map<ScheduledRecording, ScheduledRecording> modified2OriginalSchedules = new HashMap<>();
         // Simulate InputTaskScheduler.
         while (!schedulesToCheck.isEmpty()) {
@@ -853,26 +858,29 @@
                 if (modified2OriginalSchedules.containsKey(schedule)) {
                     // Schedule has been modified, which means it's already conflicted.
                     // Modify its state to partially conflicted.
-                    conflicts.put(modified2OriginalSchedules.get(schedule), true);
+                    ScheduledRecording originalSchedule = modified2OriginalSchedules.get(schedule);
+                    conflicts.put(originalSchedule, new ConflictInfo(originalSchedule, true));
                 }
             } else {
                 ScheduledRecording candidate = findReplaceableRecording(recordings, schedule);
                 if (candidate != null) {
                     if (!modified2OriginalSchedules.containsKey(candidate)) {
-                        conflicts.put(candidate, true);
+                        conflicts.put(candidate, new ConflictInfo(candidate, true));
                     }
                     recordings.remove(candidate);
                     recordings.add(schedule);
                     if (modified2OriginalSchedules.containsKey(schedule)) {
                         // Schedule has been modified, which means it's already conflicted.
                         // Modify its state to partially conflicted.
-                        conflicts.put(modified2OriginalSchedules.get(schedule), true);
+                        ScheduledRecording originalSchedule =
+                                modified2OriginalSchedules.get(schedule);
+                        conflicts.put(originalSchedule, new ConflictInfo(originalSchedule, true));
                     }
                 } else {
                     if (!modified2OriginalSchedules.containsKey(schedule)) {
                         // if schedule has been modified, it's already conflicted.
                         // No need to add it again.
-                        conflicts.put(schedule, false);
+                        conflicts.put(schedule, new ConflictInfo(schedule, false));
                     }
                     long earliestEndTime = getEarliestEndTime(recordings);
                     if (earliestEndTime < schedule.getEndTimeMs()) {
@@ -912,7 +920,14 @@
                 }
             }
         }
-        return conflicts;
+        List<ConflictInfo> result = new ArrayList<>(conflicts.values());
+        Collections.sort(result, new Comparator<ConflictInfo>() {
+            @Override
+            public int compare(ConflictInfo lhs, ConflictInfo rhs) {
+                return RESULT_COMPARATOR.compare(lhs.schedule, rhs.schedule);
+            }
+        });
+        return result;
     }
 
     private static void removeFinishedRecordings(List<ScheduledRecording> recordings,
@@ -954,6 +969,17 @@
         return earliest;
     }
 
+    @VisibleForTesting
+    static class ConflictInfo {
+        public ScheduledRecording schedule;
+        public boolean partialConflict;
+
+        ConflictInfo(ScheduledRecording schedule, boolean partialConflict) {
+            this.schedule = schedule;
+            this.partialConflict = partialConflict;
+        }
+    }
+
     /**
      * A listener which is notified the initialization of schedule manager.
      */
@@ -970,6 +996,9 @@
     public interface OnConflictStateChangeListener {
         /**
          * Called when the conflicting schedules change.
+         * <p>
+         * Note that this can be called before
+         * {@link ScheduledRecordingListener#onScheduledRecordingAdded} is called.
          *
          * @param conflict {@code true} if the {@code schedules} are the new conflicts, otherwise
          * {@code false}.
diff --git a/src/com/android/tv/dvr/DvrStorageStatusManager.java b/src/com/android/tv/dvr/DvrStorageStatusManager.java
index a653b5f..2d41d73 100644
--- a/src/com/android/tv/dvr/DvrStorageStatusManager.java
+++ b/src/com/android/tv/dvr/DvrStorageStatusManager.java
@@ -25,6 +25,7 @@
 import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.media.tv.TvContract;
+import android.media.tv.TvInputInfo;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Environment;
@@ -36,8 +37,11 @@
 import android.support.annotation.WorkerThread;
 import android.util.Log;
 
+import com.android.tv.TvApplication;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.tuner.tvinput.TunerTvInputService;
+import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
 
 import java.io.File;
@@ -294,7 +298,7 @@
                 storageMounted, storageMountedDir, storageMountedCapacity);
     }
 
-    private class CleanUpDbTask extends AsyncTask<Void, Void, Void> {
+    private class CleanUpDbTask extends AsyncTask<Void, Void, Boolean> {
         private final ContentResolver mContentResolver;
 
         private CleanUpDbTask() {
@@ -302,13 +306,15 @@
         }
 
         @Override
-        protected Void doInBackground(Void... params) {
+        protected Boolean doInBackground(Void... params) {
             @DvrStorageStatusManager.StorageStatus int storageStatus = getDvrStorageStatus();
             if (storageStatus == DvrStorageStatusManager.STORAGE_STATUS_MISSING) {
                 return null;
             }
-            List<ContentProviderOperation> ops = getDeleteOps(storageStatus
-                    == DvrStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL);
+            if (storageStatus == DvrStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL) {
+                return true;
+            }
+            List<ContentProviderOperation> ops = getDeleteOps();
             if (ops == null || ops.isEmpty()) {
                 return null;
             }
@@ -329,13 +335,28 @@
         }
 
         @Override
-        protected void onPostExecute(Void result) {
+        protected void onPostExecute(Boolean forgetStorage) {
+            if (forgetStorage != null && forgetStorage == true) {
+                DvrManager dvrManager = TvApplication.getSingletons(mContext).getDvrManager();
+                TvInputManagerHelper tvInputManagerHelper =
+                        TvApplication.getSingletons(mContext).getTvInputManagerHelper();
+                List<TvInputInfo> tvInputInfoList =
+                        tvInputManagerHelper.getTvInputInfos(true, false);
+                if (tvInputInfoList == null || tvInputInfoList.isEmpty()) {
+                    return;
+                }
+                for (TvInputInfo info : tvInputInfoList) {
+                    if (Utils.isBundledInput(info.getId())) {
+                        dvrManager.forgetStorage(info.getId());
+                    }
+                }
+            }
             if (mCleanUpDbTask == this) {
                 mCleanUpDbTask = null;
             }
         }
 
-        private List<ContentProviderOperation> getDeleteOps(boolean deleteAll) {
+        private List<ContentProviderOperation> getDeleteOps() {
             List<ContentProviderOperation> ops = new ArrayList<>();
 
             try (Cursor c = mContentResolver.query(
@@ -364,7 +385,7 @@
                         continue;
                     }
                     File recordedProgramDir = new File(dataUri.getPath());
-                    if (deleteAll || !recordedProgramDir.exists()) {
+                    if (!recordedProgramDir.exists()) {
                         ops.add(ContentProviderOperation.newDelete(
                                 TvContract.buildRecordedProgramUri(Long.parseLong(id))).build());
                     }
diff --git a/src/com/android/tv/dvr/DvrUiHelper.java b/src/com/android/tv/dvr/DvrUiHelper.java
deleted file mode 100644
index c0d3b0c..0000000
--- a/src/com/android/tv/dvr/DvrUiHelper.java
+++ /dev/null
@@ -1,450 +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.dvr;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.media.tv.TvInputManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.support.annotation.MainThread;
-import android.support.annotation.Nullable;
-import android.support.v4.app.ActivityOptionsCompat;
-import android.text.TextUtils;
-import android.widget.ImageView;
-import android.widget.Toast;
-
-import com.android.tv.MainActivity;
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.common.SoftPreconditions;
-import com.android.tv.data.Channel;
-import com.android.tv.data.Program;
-import com.android.tv.dvr.ui.DvrDetailsActivity;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrAlreadyRecordedDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrAlreadyScheduledDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrChannelRecordDurationOptionDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrChannelWatchConflictDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrInsufficientSpaceErrorDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrMissingStorageErrorDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrProgramConflictDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrScheduleDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrSmallSizedStorageErrorDialogFragment;
-import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrStopRecordingDialogFragment;
-import com.android.tv.dvr.ui.DvrSchedulesActivity;
-import com.android.tv.dvr.ui.DvrSeriesDeletionActivity;
-import com.android.tv.dvr.ui.DvrSeriesScheduledDialogActivity;
-import com.android.tv.dvr.ui.DvrSeriesSettingsActivity;
-import com.android.tv.dvr.ui.DvrStopRecordingFragment;
-import com.android.tv.dvr.ui.DvrStopSeriesRecordingDialogFragment;
-import com.android.tv.dvr.ui.DvrStopSeriesRecordingFragment;
-import com.android.tv.dvr.ui.HalfSizedDialogFragment;
-import com.android.tv.dvr.ui.list.DvrSchedulesFragment;
-import com.android.tv.dvr.ui.list.DvrSeriesSchedulesFragment;
-import com.android.tv.util.Utils;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * A helper class for DVR UI.
- */
-@MainThread
-@TargetApi(Build.VERSION_CODES.N)
-public class DvrUiHelper {
-    /**
-     * Handles the action to create the new schedule. It returns {@code true} if the schedule is
-     * added and there's no additional UI, otherwise {@code false}.
-     */
-    public static boolean handleCreateSchedule(MainActivity activity, Program program) {
-        if (program == null) {
-            return false;
-        }
-        DvrManager dvrManager = TvApplication.getSingletons(activity).getDvrManager();
-        if (!program.isEpisodic()) {
-            // One time recording.
-            dvrManager.addSchedule(program);
-            if (!dvrManager.getConflictingSchedules(program).isEmpty()) {
-                DvrUiHelper.showScheduleConflictDialog(activity, program);
-                return false;
-            }
-        } else {
-            SeriesRecording seriesRecording = dvrManager.getSeriesRecording(program);
-            if (seriesRecording == null || seriesRecording.isStopped()) {
-                DvrUiHelper.showScheduleDialog(activity, program);
-                return false;
-            } else {
-                // Show recorded program rather than the schedule.
-                RecordedProgram recordedProgram = dvrManager.getRecordedProgram(program.getTitle(),
-                        program.getSeasonNumber(), program.getEpisodeNumber());
-                if (recordedProgram != null) {
-                    DvrUiHelper.showAlreadyRecordedDialog(activity, program);
-                    return false;
-                }
-                ScheduledRecording duplicate = dvrManager.getScheduledRecording(program.getTitle(),
-                        program.getSeasonNumber(), program.getEpisodeNumber());
-                if (duplicate != null
-                        && (duplicate.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
-                        || duplicate.getState()
-                        == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
-                    DvrUiHelper.showAlreadyScheduleDialog(activity, program);
-                    return false;
-                }
-                // Just add the schedule.
-                dvrManager.addSchedule(program);
-            }
-        }
-        return true;
-
-    }
-
-    /**
-     * Checks if the storage status is good for recording and shows error messages if needed.
-     *
-     * @return true if the storage status is fine to be recorded for {@code inputId}.
-     */
-    public static boolean checkStorageStatusAndShowErrorMessage(Activity activity, String inputId) {
-        if (!Utils.isBundledInput(inputId)) {
-            return true;
-        }
-        DvrStorageStatusManager dvrStorageStatusManager =
-                TvApplication.getSingletons(activity).getDvrStorageStatusManager();
-        int status = dvrStorageStatusManager.getDvrStorageStatus();
-        if (status == DvrStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL) {
-            showDvrSmallSizedStorageErrorDialog(activity);
-            return false;
-        } else if (status == DvrStorageStatusManager.STORAGE_STATUS_MISSING) {
-            showDvrMissingStorageErrorDialog(activity, inputId);
-            return false;
-        } else if (status == DvrStorageStatusManager.STORAGE_STATUS_FREE_SPACE_INSUFFICIENT) {
-            // TODO: handle insufficient storage case.
-            return true;
-        } else {
-            return true;
-        }
-    }
-
-    /**
-     * Shows the schedule dialog.
-     */
-    public static void showScheduleDialog(MainActivity activity, Program program) {
-        if (SoftPreconditions.checkNotNull(program) == null) {
-            return;
-        }
-        Bundle args = new Bundle();
-        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
-        showDialogFragment(activity, new DvrScheduleDialogFragment(), args, true, true);
-    }
-
-    /**
-     * Shows the recording duration options dialog.
-     */
-    public static void showChannelRecordDurationOptions(MainActivity activity, Channel channel) {
-        if (SoftPreconditions.checkNotNull(channel) == null) {
-            return;
-        }
-        Bundle args = new Bundle();
-        args.putLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID, channel.getId());
-        showDialogFragment(activity, new DvrChannelRecordDurationOptionDialogFragment(), args);
-    }
-
-    /**
-     * Shows the dialog which says that the new schedule conflicts with others.
-     */
-    public static void showScheduleConflictDialog(MainActivity activity, Program program) {
-        if (program == null) {
-            return;
-        }
-        Bundle args = new Bundle();
-        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
-        showDialogFragment(activity, new DvrProgramConflictDialogFragment(), args, false, true);
-    }
-
-    /**
-     * Shows the conflict dialog for the channel watching.
-     */
-    public static void showChannelWatchConflictDialog(MainActivity activity, Channel channel) {
-        if (channel == null) {
-            return;
-        }
-        Bundle args = new Bundle();
-        args.putLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID, channel.getId());
-        showDialogFragment(activity, new DvrChannelWatchConflictDialogFragment(), args);
-    }
-
-    /**
-     * Shows DVR insufficient space error dialog.
-     */
-    public static void showDvrInsufficientSpaceErrorDialog(MainActivity activity) {
-        showDialogFragment(activity, new DvrInsufficientSpaceErrorDialogFragment(), null);
-        Utils.clearRecordingFailedReason(activity,
-                TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE);
-    }
-
-    /**
-     * Shows DVR missing storage error dialog.
-     */
-    private static void showDvrMissingStorageErrorDialog(Activity activity, String inputId) {
-        SoftPreconditions.checkArgument(!TextUtils.isEmpty(inputId));
-        Bundle args = new Bundle();
-        args.putString(DvrHalfSizedDialogFragment.KEY_INPUT_ID, inputId);
-        showDialogFragment(activity, new DvrMissingStorageErrorDialogFragment(), args);
-    }
-
-    /**
-     * Shows DVR small sized storage error dialog.
-     */
-    public static void showDvrSmallSizedStorageErrorDialog(Activity activity) {
-        showDialogFragment(activity, new DvrSmallSizedStorageErrorDialogFragment(), null);
-    }
-
-    /**
-     * Shows stop recording dialog.
-     */
-    public static void showStopRecordingDialog(Activity activity, long channelId, int reason,
-            HalfSizedDialogFragment.OnActionClickListener listener) {
-        Bundle args = new Bundle();
-        args.putLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID, channelId);
-        args.putInt(DvrStopRecordingFragment.KEY_REASON, reason);
-        DvrHalfSizedDialogFragment fragment = new DvrStopRecordingDialogFragment();
-        fragment.setOnActionClickListener(listener);
-        showDialogFragment(activity, fragment, args);
-    }
-
-    /**
-     * Shows "already scheduled" dialog.
-     */
-    public static void showAlreadyScheduleDialog(MainActivity activity, Program program) {
-        if (program == null) {
-            return;
-        }
-        Bundle args = new Bundle();
-        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
-        showDialogFragment(activity, new DvrAlreadyScheduledDialogFragment(), args, false, true);
-    }
-
-    /**
-     * Shows "already recorded" dialog.
-     */
-    public static void showAlreadyRecordedDialog(MainActivity activity, Program program) {
-        if (program == null) {
-            return;
-        }
-        Bundle args = new Bundle();
-        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
-        showDialogFragment(activity, new DvrAlreadyRecordedDialogFragment(), args, false, true);
-    }
-
-    private static void showDialogFragment(Activity activity,
-            DvrHalfSizedDialogFragment dialogFragment, Bundle args) {
-        showDialogFragment(activity, dialogFragment, args, false, false);
-    }
-
-    private static void showDialogFragment(Activity activity,
-            DvrHalfSizedDialogFragment dialogFragment, Bundle args, boolean keepSidePanelHistory,
-            boolean keepProgramGuide) {
-        dialogFragment.setArguments(args);
-        if (activity instanceof MainActivity) {
-            ((MainActivity) activity).getOverlayManager()
-                    .showDialogFragment(DvrHalfSizedDialogFragment.DIALOG_TAG, dialogFragment,
-                            keepSidePanelHistory, keepProgramGuide);
-        } else {
-            dialogFragment.show(activity.getFragmentManager(),
-                    DvrHalfSizedDialogFragment.DIALOG_TAG);
-        }
-    }
-
-    /**
-     * Checks whether channel watch conflict dialog is open or not.
-     */
-    public static boolean isChannelWatchConflictDialogShown(MainActivity activity) {
-        return activity.getOverlayManager().getCurrentDialog() instanceof
-                DvrChannelWatchConflictDialogFragment;
-    }
-
-    private static ScheduledRecording getEarliestScheduledRecording(List<ScheduledRecording>
-            recordings) {
-        ScheduledRecording earlistScheduledRecording = null;
-        if (!recordings.isEmpty()) {
-            Collections.sort(recordings,
-                    ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR);
-            earlistScheduledRecording = recordings.get(0);
-        }
-        return earlistScheduledRecording;
-    }
-
-    /**
-     * Shows the schedules activity to resolve the tune conflict.
-     */
-    public static void startSchedulesActivityForTuneConflict(Context context, Channel channel) {
-        if (channel == null) {
-            return;
-        }
-        List<ScheduledRecording> conflicts = TvApplication.getSingletons(context).getDvrManager()
-                .getConflictingSchedulesForTune(channel.getId());
-        startSchedulesActivity(context, getEarliestScheduledRecording(conflicts));
-    }
-
-    /**
-     * Shows the schedules activity to resolve the one time recording conflict.
-     */
-    public static void startSchedulesActivityForOneTimeRecordingConflict(Context context,
-            List<ScheduledRecording> conflicts) {
-        startSchedulesActivity(context, getEarliestScheduledRecording(conflicts));
-    }
-
-    /**
-     * Shows the schedules activity with full schedule.
-     */
-    public static void startSchedulesActivity(Context context, ScheduledRecording
-            focusedScheduledRecording) {
-        Intent intent = new Intent(context, DvrSchedulesActivity.class);
-        intent.putExtra(DvrSchedulesActivity.KEY_SCHEDULES_TYPE,
-                DvrSchedulesActivity.TYPE_FULL_SCHEDULE);
-        if (focusedScheduledRecording != null) {
-            intent.putExtra(DvrSchedulesFragment.SCHEDULES_KEY_SCHEDULED_RECORDING,
-                    focusedScheduledRecording);
-        }
-        context.startActivity(intent);
-    }
-
-    /**
-     * Shows the schedules activity for series recording.
-     */
-    public static void startSchedulesActivityForSeries(Context context,
-            SeriesRecording seriesRecording) {
-        Intent intent = new Intent(context, DvrSchedulesActivity.class);
-        intent.putExtra(DvrSchedulesActivity.KEY_SCHEDULES_TYPE,
-                DvrSchedulesActivity.TYPE_SERIES_SCHEDULE);
-        intent.putExtra(DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING,
-                seriesRecording);
-        context.startActivity(intent);
-    }
-
-    /**
-     * Shows the series settings activity.
-     *
-     * @param channelIds Channel ID list which has programs belonging to the series.
-     */
-    public static void startSeriesSettingsActivity(Context context, long seriesRecordingId,
-            @Nullable long[] channelIds, boolean removeEmptySeriesSchedule,
-            boolean isWindowTranslucent, boolean showViewScheduleOptionInDialog) {
-        Intent intent = new Intent(context, DvrSeriesSettingsActivity.class);
-        intent.putExtra(DvrSeriesSettingsActivity.SERIES_RECORDING_ID, seriesRecordingId);
-        intent.putExtra(DvrSeriesSettingsActivity.CHANNEL_ID_LIST, channelIds);
-        intent.putExtra(DvrSeriesSettingsActivity.REMOVE_EMPTY_SERIES_RECORDING,
-                removeEmptySeriesSchedule);
-        intent.putExtra(DvrSeriesSettingsActivity.IS_WINDOW_TRANSLUCENT, isWindowTranslucent);
-        intent.putExtra(DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG,
-                showViewScheduleOptionInDialog);
-        context.startActivity(intent);
-    }
-
-    /**
-     * Shows "series recording scheduled" dialog activity.
-     */
-    public static void StartSeriesScheduledDialogActivity(Context context,
-            SeriesRecording seriesRecording, boolean showViewScheduleOptionInDialog) {
-        if (seriesRecording == null) {
-            return;
-        }
-        Intent intent = new Intent(context, DvrSeriesScheduledDialogActivity.class);
-        intent.putExtra(DvrSeriesScheduledDialogActivity.SERIES_RECORDING_ID,
-                seriesRecording.getId());
-        intent.putExtra(DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION,
-                showViewScheduleOptionInDialog);
-        context.startActivity(intent);
-    }
-
-    /**
-     * Shows the details activity for the DVR items. The type of DVR items may be
-     * {@link ScheduledRecording}, {@link RecordedProgram}, or {@link SeriesRecording}.
-     */
-    public static void startDetailsActivity(Activity activity, Object dvrItem,
-            @Nullable ImageView imageView, boolean hideViewSchedule) {
-        if (dvrItem == null) {
-            return;
-        }
-        Intent intent = new Intent(activity, DvrDetailsActivity.class);
-        long recordingId;
-        int viewType;
-        if (dvrItem instanceof ScheduledRecording) {
-            ScheduledRecording schedule = (ScheduledRecording) dvrItem;
-            recordingId = schedule.getId();
-            if (schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED) {
-                viewType = DvrDetailsActivity.SCHEDULED_RECORDING_VIEW;
-            } else if (schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
-                viewType = DvrDetailsActivity.CURRENT_RECORDING_VIEW;
-            } else {
-                return;
-            }
-        } else if (dvrItem instanceof RecordedProgram) {
-            recordingId = ((RecordedProgram) dvrItem).getId();
-            viewType = DvrDetailsActivity.RECORDED_PROGRAM_VIEW;
-        } else if (dvrItem instanceof SeriesRecording) {
-            recordingId = ((SeriesRecording) dvrItem).getId();
-            viewType = DvrDetailsActivity.SERIES_RECORDING_VIEW;
-        } else {
-            return;
-        }
-        intent.putExtra(DvrDetailsActivity.RECORDING_ID, recordingId);
-        intent.putExtra(DvrDetailsActivity.DETAILS_VIEW_TYPE, viewType);
-        intent.putExtra(DvrDetailsActivity.HIDE_VIEW_SCHEDULE, hideViewSchedule);
-        Bundle bundle = null;
-        if (imageView != null) {
-            bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, imageView,
-                    DvrDetailsActivity.SHARED_ELEMENT_NAME).toBundle();
-        }
-        activity.startActivity(intent, bundle);
-    }
-
-    /**
-     * Shows the cancel all dialog for series schedules list.
-     */
-    public static void showCancelAllSeriesRecordingDialog(DvrSchedulesActivity activity,
-            SeriesRecording seriesRecording) {
-        DvrStopSeriesRecordingDialogFragment dvrStopSeriesRecordingDialogFragment =
-                new DvrStopSeriesRecordingDialogFragment();
-        Bundle arguments = new Bundle();
-        arguments.putParcelable(DvrStopSeriesRecordingFragment.KEY_SERIES_RECORDING,
-                seriesRecording);
-        dvrStopSeriesRecordingDialogFragment.setArguments(arguments);
-        dvrStopSeriesRecordingDialogFragment.show(activity.getFragmentManager(),
-                DvrStopSeriesRecordingDialogFragment.DIALOG_TAG);
-    }
-
-    /**
-     * Shows the series deletion activity.
-     */
-    public static void startSeriesDeletionActivity(Context context, long seriesRecordingId) {
-        Intent intent = new Intent(context, DvrSeriesDeletionActivity.class);
-        intent.putExtra(DvrSeriesDeletionActivity.SERIES_RECORDING_ID, seriesRecordingId);
-        context.startActivity(intent);
-    }
-
-    public static void showAddScheduleToast(Context context,
-            String title, long startTimeMs, long endTimeMs) {
-        String msg = (startTimeMs > System.currentTimeMillis()) ?
-            context.getString(R.string.dvr_msg_program_scheduled, title)
-            : context.getString(R.string.dvr_msg_current_program_scheduled, title,
-                    Utils.toTimeString(endTimeMs, false));
-        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
-    }
-}
diff --git a/src/com/android/tv/dvr/DvrWatchedPositionManager.java b/src/com/android/tv/dvr/DvrWatchedPositionManager.java
index 4eada74..da6ddb1 100644
--- a/src/com/android/tv/dvr/DvrWatchedPositionManager.java
+++ b/src/com/android/tv/dvr/DvrWatchedPositionManager.java
@@ -22,6 +22,7 @@
 import android.support.annotation.IntDef;
 
 import com.android.tv.common.SharedPreferencesUtils;
+import com.android.tv.dvr.data.RecordedProgram;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -36,9 +37,6 @@
  * It will remember and provides previous watched position of DVR playback.
  */
 public class DvrWatchedPositionManager {
-    private final static String TAG = "DvrWatchedPositionManager";
-    private final boolean DEBUG = false;
-
     private SharedPreferences mWatchedPositions;
     private final Map<Long, Set> mListeners = new HashMap<>();
 
diff --git a/src/com/android/tv/dvr/Scheduler.java b/src/com/android/tv/dvr/Scheduler.java
deleted file mode 100644
index ce78e1b..0000000
--- a/src/com/android/tv/dvr/Scheduler.java
+++ /dev/null
@@ -1,283 +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.dvr;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.Context;
-import android.content.Intent;
-import android.media.tv.TvInputInfo;
-import android.media.tv.TvInputManager.TvInputCallback;
-import android.os.Looper;
-import android.support.annotation.MainThread;
-import android.support.annotation.VisibleForTesting;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Range;
-
-import com.android.tv.InputSessionManager;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.ChannelDataManager.Listener;
-import com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
-import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
-import com.android.tv.util.Clock;
-import com.android.tv.util.TvInputManagerHelper;
-import com.android.tv.util.Utils;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * The core class to manage schedule and run actual recording.
- */
-@MainThread
-public class Scheduler extends TvInputCallback implements ScheduledRecordingListener {
-    private static final String TAG = "Scheduler";
-    private static final boolean DEBUG = false;
-
-    private final static long SOON_DURATION_IN_MS = TimeUnit.MINUTES.toMillis(5);
-    @VisibleForTesting final static long MS_TO_WAKE_BEFORE_START = TimeUnit.MINUTES.toMillis(1);
-
-    private final Looper mLooper;
-    private final InputSessionManager mSessionManager;
-    private final WritableDvrDataManager mDataManager;
-    private final DvrManager mDvrManager;
-    private final ChannelDataManager mChannelDataManager;
-    private final TvInputManagerHelper mInputManager;
-    private final Context mContext;
-    private final Clock mClock;
-    private final AlarmManager mAlarmManager;
-
-    private final Map<String, InputTaskScheduler> mInputSchedulerMap = new ArrayMap<>();
-    private long mLastStartTimePendingMs;
-
-    public Scheduler(Looper looper, DvrManager dvrManager, InputSessionManager sessionManager,
-            WritableDvrDataManager dataManager, ChannelDataManager channelDataManager,
-            TvInputManagerHelper inputManager, Context context, Clock clock,
-            AlarmManager alarmManager) {
-        mLooper = looper;
-        mDvrManager = dvrManager;
-        mSessionManager = sessionManager;
-        mDataManager = dataManager;
-        mChannelDataManager = channelDataManager;
-        mInputManager = inputManager;
-        mContext = context;
-        mClock = clock;
-        mAlarmManager = alarmManager;
-    }
-
-    /**
-     * Starts the scheduler.
-     */
-    public void start() {
-        mDataManager.addScheduledRecordingListener(this);
-        mInputManager.addCallback(this);
-        if (mDataManager.isDvrScheduleLoadFinished() && mChannelDataManager.isDbLoadFinished()) {
-            updateInternal();
-        } else {
-            if (!mDataManager.isDvrScheduleLoadFinished()) {
-                mDataManager.addDvrScheduleLoadFinishedListener(
-                        new OnDvrScheduleLoadFinishedListener() {
-                            @Override
-                            public void onDvrScheduleLoadFinished() {
-                                mDataManager.removeDvrScheduleLoadFinishedListener(this);
-                                updateInternal();
-                            }
-                        });
-            }
-            if (!mChannelDataManager.isDbLoadFinished()) {
-                mChannelDataManager.addListener(new Listener() {
-                    @Override
-                    public void onLoadFinished() {
-                        mChannelDataManager.removeListener(this);
-                        updateInternal();
-                    }
-
-                    @Override
-                    public void onChannelListUpdated() { }
-
-                    @Override
-                    public void onChannelBrowsableChanged() { }
-                });
-            }
-        }
-    }
-
-    /**
-     * Stops the scheduler.
-     */
-    public void stop() {
-        for (InputTaskScheduler inputTaskScheduler : mInputSchedulerMap.values()) {
-            inputTaskScheduler.stop();
-        }
-        mInputManager.removeCallback(this);
-        mDataManager.removeScheduledRecordingListener(this);
-    }
-
-    private void updatePendingRecordings() {
-        List<ScheduledRecording> scheduledRecordings = mDataManager
-                .getScheduledRecordings(new Range<>(mLastStartTimePendingMs,
-                        mClock.currentTimeMillis() + SOON_DURATION_IN_MS),
-                        ScheduledRecording.STATE_RECORDING_NOT_STARTED);
-        for (ScheduledRecording r : scheduledRecordings) {
-            scheduleRecordingSoon(r);
-        }
-    }
-
-    /**
-     * Start recording that will happen soon, and set the next alarm time.
-     */
-    public void update() {
-        if (DEBUG) Log.d(TAG, "update");
-        updateInternal();
-    }
-
-    private void updateInternal() {
-        if (isInitialized()) {
-            updatePendingRecordings();
-            updateNextAlarm();
-        }
-    }
-
-    private boolean isInitialized() {
-        return mDataManager.isDvrScheduleLoadFinished() && mChannelDataManager.isDbLoadFinished();
-    }
-
-    @Override
-    public void onScheduledRecordingAdded(ScheduledRecording... schedules) {
-        if (DEBUG) Log.d(TAG, "added " + Arrays.asList(schedules));
-        if (!isInitialized()) {
-            return;
-        }
-        handleScheduleChange(schedules);
-    }
-
-    @Override
-    public void onScheduledRecordingRemoved(ScheduledRecording... schedules) {
-        if (DEBUG) Log.d(TAG, "removed " + Arrays.asList(schedules));
-        if (!isInitialized()) {
-            return;
-        }
-        boolean needToUpdateAlarm = false;
-        for (ScheduledRecording schedule : schedules) {
-            InputTaskScheduler scheduler = mInputSchedulerMap.get(schedule.getInputId());
-            if (scheduler != null) {
-                scheduler.removeSchedule(schedule);
-                needToUpdateAlarm = true;
-            }
-        }
-        if (needToUpdateAlarm) {
-            updateNextAlarm();
-        }
-    }
-
-    @Override
-    public void onScheduledRecordingStatusChanged(ScheduledRecording... schedules) {
-        if (DEBUG) Log.d(TAG, "state changed " + Arrays.asList(schedules));
-        if (!isInitialized()) {
-            return;
-        }
-        // Update the recordings.
-        for (ScheduledRecording schedule : schedules) {
-            InputTaskScheduler scheduler = mInputSchedulerMap.get(schedule.getInputId());
-            if (scheduler != null) {
-                scheduler.updateSchedule(schedule);
-            }
-        }
-        handleScheduleChange(schedules);
-    }
-
-    private void handleScheduleChange(ScheduledRecording... schedules) {
-        boolean needToUpdateAlarm = false;
-        for (ScheduledRecording schedule : schedules) {
-            if (schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED) {
-                if (startsWithin(schedule, SOON_DURATION_IN_MS)) {
-                    scheduleRecordingSoon(schedule);
-                } else {
-                    needToUpdateAlarm = true;
-                }
-            }
-        }
-        if (needToUpdateAlarm) {
-            updateNextAlarm();
-        }
-    }
-
-    private void scheduleRecordingSoon(ScheduledRecording schedule) {
-        TvInputInfo input = Utils.getTvInputInfoForInputId(mContext, schedule.getInputId());
-        if (input == null) {
-            Log.e(TAG, "Can't find input for " + schedule);
-            mDataManager.changeState(schedule, ScheduledRecording.STATE_RECORDING_FAILED);
-            return;
-        }
-        if (!input.canRecord() || input.getTunerCount() <= 0) {
-            Log.e(TAG, "TV input doesn't support recording: " + input);
-            mDataManager.changeState(schedule, ScheduledRecording.STATE_RECORDING_FAILED);
-            return;
-        }
-        InputTaskScheduler scheduler = mInputSchedulerMap.get(input.getId());
-        if (scheduler == null) {
-            scheduler = new InputTaskScheduler(mContext, input, mLooper, mChannelDataManager,
-                    mDvrManager, mDataManager, mSessionManager, mClock);
-            mInputSchedulerMap.put(input.getId(), scheduler);
-        }
-        scheduler.addSchedule(schedule);
-        if (mLastStartTimePendingMs < schedule.getStartTimeMs()) {
-            mLastStartTimePendingMs = schedule.getStartTimeMs();
-        }
-    }
-
-    private void updateNextAlarm() {
-        long nextStartTime = mDataManager.getNextScheduledStartTimeAfter(
-                Math.max(mLastStartTimePendingMs, mClock.currentTimeMillis()));
-        if (nextStartTime != DvrDataManager.NEXT_START_TIME_NOT_FOUND) {
-            long wakeAt = nextStartTime - MS_TO_WAKE_BEFORE_START;
-            if (DEBUG) Log.d(TAG, "Set alarm to record at " + wakeAt);
-            Intent intent = new Intent(mContext, DvrStartRecordingReceiver.class);
-            PendingIntent alarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
-            // This will cancel the previous alarm.
-            mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, wakeAt, alarmIntent);
-        } else {
-            if (DEBUG) Log.d(TAG, "No future recording, alarm not set");
-        }
-    }
-
-    @VisibleForTesting
-    boolean startsWithin(ScheduledRecording scheduledRecording, long durationInMs) {
-        return mClock.currentTimeMillis() >= scheduledRecording.getStartTimeMs() - durationInMs;
-    }
-
-    // No need to remove input task scheduler when the input is removed. If the input is removed
-    // temporarily, the scheduler should keep the non-started schedules.
-    @Override
-    public void onInputUpdated(String inputId) {
-        InputTaskScheduler scheduler = mInputSchedulerMap.get(inputId);
-        if (scheduler != null) {
-            scheduler.updateTvInputInfo(Utils.getTvInputInfoForInputId(mContext, inputId));
-        }
-    }
-
-    @Override
-    public void onTvInputInfoUpdated(TvInputInfo input) {
-        InputTaskScheduler scheduler = mInputSchedulerMap.get(input.getId());
-        if (scheduler != null) {
-            scheduler.updateTvInputInfo(input);
-        }
-    }
-}
diff --git a/src/com/android/tv/dvr/WritableDvrDataManager.java b/src/com/android/tv/dvr/WritableDvrDataManager.java
index bf72d91..129ba15 100644
--- a/src/com/android/tv/dvr/WritableDvrDataManager.java
+++ b/src/com/android/tv/dvr/WritableDvrDataManager.java
@@ -18,7 +18,9 @@
 
 import android.support.annotation.MainThread;
 
-import com.android.tv.dvr.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.SeriesRecording;
 
 /**
  * Full data manager.
@@ -27,7 +29,7 @@
  * for internal use only. Do not call them from UI directly.
  */
 @MainThread
-interface WritableDvrDataManager extends DvrDataManager {
+public interface WritableDvrDataManager extends DvrDataManager {
     /**
      * Adds new recordings.
      */
diff --git a/src/com/android/tv/dvr/IdGenerator.java b/src/com/android/tv/dvr/data/IdGenerator.java
similarity index 97%
rename from src/com/android/tv/dvr/IdGenerator.java
rename to src/com/android/tv/dvr/data/IdGenerator.java
index 0ed6362..2ade1da 100644
--- a/src/com/android/tv/dvr/IdGenerator.java
+++ b/src/com/android/tv/dvr/data/IdGenerator.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.data;
 
 import java.util.concurrent.atomic.AtomicLong;
 
diff --git a/src/com/android/tv/dvr/RecordedProgram.java b/src/com/android/tv/dvr/data/RecordedProgram.java
similarity index 91%
rename from src/com/android/tv/dvr/RecordedProgram.java
rename to src/com/android/tv/dvr/data/RecordedProgram.java
index dd744f8..2e953a5 100644
--- a/src/com/android/tv/dvr/RecordedProgram.java
+++ b/src/com/android/tv/dvr/data/RecordedProgram.java
@@ -14,22 +14,23 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
-
-import static android.media.tv.TvContract.RecordedPrograms;
+package com.android.tv.dvr.data;
 
 import android.annotation.TargetApi;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.Context;
 import android.database.Cursor;
+import android.media.tv.TvContentRating;
 import android.media.tv.TvContract;
+import android.media.tv.TvContract.RecordedPrograms;
 import android.net.Uri;
 import android.os.Build;
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
 
 import com.android.tv.common.R;
+import com.android.tv.common.TvContentRatingCache;
 import com.android.tv.data.BaseProgram;
 import com.android.tv.data.GenreItems;
 import com.android.tv.data.InternalDataUtils;
@@ -105,7 +106,8 @@
                 .setVideoWidth(cursor.getInt(index++))
                 .setVideoHeight(cursor.getInt(index++))
                 .setAudioLanguage(cursor.getString(index++))
-                .setContentRating(cursor.getString(index++))
+                .setContentRatings(
+                        TvContentRatingCache.getInstance().getRatings(cursor.getString(index++)))
                 .setPosterArtUri(cursor.getString(index++))
                 .setThumbnailUri(cursor.getString(index++))
                 .setSearchable(cursor.getInt(index++) == 1)
@@ -156,7 +158,8 @@
             values.put(RecordedPrograms.COLUMN_VIDEO_HEIGHT, recordedProgram.mVideoHeight);
         }
         values.put(RecordedPrograms.COLUMN_AUDIO_LANGUAGE, recordedProgram.mAudioLanguage);
-        values.put(RecordedPrograms.COLUMN_CONTENT_RATING, recordedProgram.mContentRating);
+        values.put(RecordedPrograms.COLUMN_CONTENT_RATING,
+                TvContentRatingCache.contentRatingsToString(recordedProgram.mContentRatings));
         values.put(RecordedPrograms.COLUMN_POSTER_ART_URI, recordedProgram.mPosterArtUri);
         values.put(RecordedPrograms.COLUMN_THUMBNAIL_URI, recordedProgram.mThumbnailUri);
         values.put(RecordedPrograms.COLUMN_SEARCHABLE, recordedProgram.mSearchable ? 1 : 0);
@@ -201,7 +204,7 @@
         private int mVideoWidth;
         private int mVideoHeight;
         private String mAudioLanguage;
-        private String mContentRating;
+        private TvContentRating[] mContentRatings;
         private String mPosterArtUri;
         private String mThumbnailUri;
         private boolean mSearchable = true;
@@ -326,8 +329,8 @@
             return this;
         }
 
-        public Builder setContentRating(String contentRating) {
-            mContentRating = contentRating;
+        public Builder setContentRatings(TvContentRating[] contentRatings) {
+            mContentRatings = contentRatings;
             return this;
         }
 
@@ -404,15 +407,17 @@
         }
 
         public RecordedProgram build() {
-            // Generate the series ID for the episodic program of other TV input.
-            if (TextUtils.isEmpty(mSeriesId)
-                    && !TextUtils.isEmpty(mEpisodeNumber)) {
+            if (TextUtils.isEmpty(mTitle)) {
+                // If title is null, series cannot be generated for this program.
+                setSeriesId(null);
+            } else if (TextUtils.isEmpty(mSeriesId) && !TextUtils.isEmpty(mEpisodeNumber)) {
+                // If series ID is not set, generate it for the episodic program of other TV input.
                 setSeriesId(BaseProgram.generateSeriesId(mPackageName, mTitle));
             }
             return new RecordedProgram(mId, mPackageName, mInputId, mChannelId, mTitle, mSeriesId,
                     mSeasonNumber, mSeasonTitle, mEpisodeNumber, mEpisodeTitle, mStartTimeUtcMillis,
                     mEndTimeUtcMillis, mBroadcastGenres, mCanonicalGenres, mShortDescription,
-                    mLongDescription, mVideoWidth, mVideoHeight, mAudioLanguage, mContentRating,
+                    mLongDescription, mVideoWidth, mVideoHeight, mAudioLanguage, mContentRatings,
                     mPosterArtUri, mThumbnailUri, mSearchable, mDataUri, mDataBytes,
                     mDurationMillis, mExpireTimeUtcMillis, mInternalProviderFlag1,
                     mInternalProviderFlag2, mInternalProviderFlag3, mInternalProviderFlag4,
@@ -443,7 +448,7 @@
                 .setVideoWidth(orig.getVideoWidth())
                 .setVideoHeight(orig.getVideoHeight())
                 .setAudioLanguage(orig.getAudioLanguage())
-                .setContentRating(orig.getContentRating())
+                .setContentRatings(orig.getContentRatings())
                 .setPosterArtUri(orig.getPosterArtUri())
                 .setThumbnailUri(orig.getThumbnailUri())
                 .setSearchable(orig.isSearchable())
@@ -488,7 +493,7 @@
     private final int mVideoWidth;
     private final int mVideoHeight;
     private final String mAudioLanguage;
-    private final String mContentRating;
+    private final TvContentRating[] mContentRatings;
     private final String mPosterArtUri;
     private final String mThumbnailUri;
     private final boolean mSearchable;
@@ -507,10 +512,11 @@
             String episodeNumber, String episodeTitle, long startTimeUtcMillis,
             long endTimeUtcMillis, String[] broadcastGenres, String[] canonicalGenres,
             String shortDescription, String longDescription, int videoWidth, int videoHeight,
-            String audioLanguage, String contentRating, String posterArtUri, String thumbnailUri,
-            boolean searchable, Uri dataUri, long dataBytes, long durationMillis,
-            long expireTimeUtcMillis, int internalProviderFlag1, int internalProviderFlag2,
-            int internalProviderFlag3, int internalProviderFlag4, int versionNumber) {
+            String audioLanguage, TvContentRating[] contentRatings, String posterArtUri,
+            String thumbnailUri, boolean searchable, Uri dataUri, long dataBytes,
+            long durationMillis, long expireTimeUtcMillis, int internalProviderFlag1,
+            int internalProviderFlag2, int internalProviderFlag3, int internalProviderFlag4,
+            int versionNumber) {
         mId = id;
         mPackageName = packageName;
         mInputId = inputId;
@@ -531,7 +537,7 @@
         mVideoHeight = videoHeight;
 
         mAudioLanguage = audioLanguage;
-        mContentRating = contentRating;
+        mContentRatings = contentRatings;
         mPosterArtUri = posterArtUri;
         mThumbnailUri = thumbnailUri;
         mSearchable = searchable;
@@ -578,8 +584,10 @@
         return mChannelId;
     }
 
-    public String getContentRating() {
-        return mContentRating;
+    @Nullable
+    @Override
+    public TvContentRating[] getContentRatings() {
+        return mContentRatings;
     }
 
     public Uri getDataUri() {
@@ -605,43 +613,11 @@
         return mEpisodeNumber;
     }
 
+    @Override
     public String getEpisodeTitle() {
         return mEpisodeTitle;
     }
 
-    @Override
-    public String getEpisodeDisplayTitle(Context context) {
-        if (!TextUtils.isEmpty(mEpisodeNumber)) {
-            String episodeTitle = mEpisodeTitle == null ? "" : mEpisodeTitle;
-            if (TextUtils.equals(mSeasonNumber, "0")) {
-                // Do not show "S0: ".
-                return String.format(context.getResources().getString(
-                        R.string.display_episode_title_format_no_season_number),
-                        mEpisodeNumber, episodeTitle);
-            } else {
-                return String.format(context.getResources().getString(
-                        R.string.display_episode_title_format),
-                        mSeasonNumber, mEpisodeNumber, episodeTitle);
-            }
-        }
-        return mEpisodeTitle;
-    }
-
-    @Nullable
-    @Override
-    public String getTitleWithEpisodeNumber(Context context) {
-        if (TextUtils.isEmpty(mTitle)) {
-            return mTitle;
-        }
-        if (TextUtils.isEmpty(mSeasonNumber) || mSeasonNumber.equals("0")) {
-            return TextUtils.isEmpty(mEpisodeNumber) ? mTitle : context.getString(
-                    R.string.program_title_with_episode_number_no_season, mTitle, mEpisodeNumber);
-        } else {
-            return context.getString(R.string.program_title_with_episode_number, mTitle,
-                    mSeasonNumber, mEpisodeNumber);
-        }
-    }
-
     @Nullable
     public String getEpisodeDisplayNumber(Context context) {
         if (!TextUtils.isEmpty(mEpisodeNumber)) {
@@ -796,7 +772,7 @@
                 Objects.equals(mShortDescription, that.mShortDescription) &&
                 Objects.equals(mLongDescription, that.mLongDescription) &&
                 Objects.equals(mAudioLanguage, that.mAudioLanguage) &&
-                Objects.equals(mContentRating, that.mContentRating) &&
+                Arrays.equals(mContentRatings, that.mContentRatings) &&
                 Objects.equals(mPosterArtUri, that.mPosterArtUri) &&
                 Objects.equals(mThumbnailUri, that.mThumbnailUri);
     }
@@ -831,7 +807,8 @@
                 ", mVideoHeight=" + mVideoHeight +
                 ", mVideoWidth=" + mVideoWidth +
                 ", mAudioLanguage='" + mAudioLanguage + '\'' +
-                ", mContentRating='" + mContentRating + '\'' +
+                ", mContentRatings='" +
+                        TvContentRatingCache.contentRatingsToString(mContentRatings) + '\'' +
                 ", mPosterArtUri=" + mPosterArtUri +
                 ", mThumbnailUri=" + mThumbnailUri +
                 ", mSearchable=" + mSearchable +
diff --git a/src/com/android/tv/dvr/ScheduledRecording.java b/src/com/android/tv/dvr/data/ScheduledRecording.java
similarity index 97%
rename from src/com/android/tv/dvr/ScheduledRecording.java
rename to src/com/android/tv/dvr/data/ScheduledRecording.java
index 2bda10e..5d11c0f 100644
--- a/src/com/android/tv/dvr/ScheduledRecording.java
+++ b/src/com/android/tv/dvr/data/ScheduledRecording.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.data;
 
 import android.content.ContentValues;
 import android.content.Context;
@@ -22,14 +22,15 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.support.annotation.IntDef;
-import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Range;
 
 import com.android.tv.R;
+import com.android.tv.TvApplication;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.data.Program;
+import com.android.tv.dvr.DvrScheduleManager;
 import com.android.tv.dvr.provider.DvrContract.Schedules;
 import com.android.tv.util.CompositeComparator;
 import com.android.tv.util.Utils;
@@ -43,7 +44,6 @@
 /**
  * A data class for one recording contents.
  */
-@VisibleForTesting
 public final class ScheduledRecording implements Parcelable {
     private static final String TAG = "ScheduledRecording";
 
@@ -141,7 +141,6 @@
     /**
      * Creates a new Builder with the values set from the {@link RecordedProgram}.
      */
-    @VisibleForTesting
     public static Builder builder(RecordedProgram p) {
         boolean isProgramRecording = !TextUtils.isEmpty(p.getTitle());
         return new Builder()
@@ -667,23 +666,19 @@
     }
 
     /**
-     * Returns the program's title withe its season and episode number.
+     * Returns the program's display title, if the program title is not null, returns program title.
+     * Otherwise returns the channel name.
      */
-    public String getProgramTitleWithEpisodeNumber(Context context) {
-        if (TextUtils.isEmpty(mProgramTitle)) {
+    public String getProgramDisplayTitle(Context context) {
+        if (!TextUtils.isEmpty(mProgramTitle)) {
             return mProgramTitle;
         }
-        if (TextUtils.isEmpty(mSeasonNumber) || mSeasonNumber.equals("0")) {
-            return TextUtils.isEmpty(mEpisodeNumber) ? mProgramTitle : context.getString(
-                    R.string.program_title_with_episode_number_no_season, mProgramTitle,
-                    mEpisodeNumber);
-        } else {
-            return context.getString(R.string.program_title_with_episode_number, mProgramTitle,
-                    mSeasonNumber, mEpisodeNumber);
-        }
+        Channel channel = TvApplication.getSingletons(context).getChannelDataManager()
+                .getChannel(mChannelId);
+        return channel != null ? channel.getDisplayName()
+                : context.getString(R.string.no_program_information);
     }
 
-
     /**
      * Converts a string to a @RecordingType int, defaulting to {@link #TYPE_TIMED}.
      */
diff --git a/src/com/android/tv/dvr/data/SeasonEpisodeNumber.java b/src/com/android/tv/dvr/data/SeasonEpisodeNumber.java
new file mode 100644
index 0000000..89533db
--- /dev/null
+++ b/src/com/android/tv/dvr/data/SeasonEpisodeNumber.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 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.dvr.data;
+
+import android.text.TextUtils;
+
+import java.util.Objects;
+
+/**
+ * A plain java object which includes the season/episode number for the series recording.
+ */
+public class SeasonEpisodeNumber {
+    public final long seriesRecordingId;
+    public final String seasonNumber;
+    public final String episodeNumber;
+
+    /**
+     * Creates a new Builder with the values set from an existing {@link ScheduledRecording}.
+     */
+    public SeasonEpisodeNumber(ScheduledRecording r) {
+        this(r.getSeriesRecordingId(), r.getSeasonNumber(), r.getEpisodeNumber());
+    }
+
+    public SeasonEpisodeNumber(long seriesRecordingId, String seasonNumber, String episodeNumber) {
+        this.seriesRecordingId = seriesRecordingId;
+        this.seasonNumber = seasonNumber;
+        this.episodeNumber = episodeNumber;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof SeasonEpisodeNumber)
+                || TextUtils.isEmpty(seasonNumber) || TextUtils.isEmpty(episodeNumber)) {
+            return false;
+        }
+        SeasonEpisodeNumber that = (SeasonEpisodeNumber) o;
+        return seriesRecordingId == that.seriesRecordingId
+                && Objects.equals(seasonNumber, that.seasonNumber)
+                && Objects.equals(episodeNumber, that.episodeNumber);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(seriesRecordingId, seasonNumber, episodeNumber);
+    }
+
+    @Override
+    public String toString() {
+        return "SeasonEpisodeNumber{" +
+                "seriesRecordingId=" + seriesRecordingId +
+                ", seasonNumber='" + seasonNumber +
+                ", episodeNumber=" + episodeNumber +
+                '}';
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/SeriesInfo.java b/src/com/android/tv/dvr/data/SeriesInfo.java
similarity index 98%
rename from src/com/android/tv/dvr/SeriesInfo.java
rename to src/com/android/tv/dvr/data/SeriesInfo.java
index 30256dc..a0dec4a 100644
--- a/src/com/android/tv/dvr/SeriesInfo.java
+++ b/src/com/android/tv/dvr/data/SeriesInfo.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.data;
 
 /**
  * Series information.
diff --git a/src/com/android/tv/dvr/SeriesRecording.java b/src/com/android/tv/dvr/data/SeriesRecording.java
similarity index 99%
rename from src/com/android/tv/dvr/SeriesRecording.java
rename to src/com/android/tv/dvr/data/SeriesRecording.java
index f0690f5..822e732 100644
--- a/src/com/android/tv/dvr/SeriesRecording.java
+++ b/src/com/android/tv/dvr/data/SeriesRecording.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.data;
 
 import android.content.ContentValues;
 import android.database.Cursor;
@@ -26,6 +26,7 @@
 
 import com.android.tv.data.BaseProgram;
 import com.android.tv.data.Program;
+import com.android.tv.dvr.DvrScheduleManager;
 import com.android.tv.dvr.provider.DvrContract.SeriesRecordings;
 import com.android.tv.util.Utils;
 
@@ -128,7 +129,6 @@
     /**
      * Creates a new Builder with the values set from an existing {@link SeriesRecording}.
      */
-    @VisibleForTesting
     public static Builder buildFrom(SeriesRecording r) {
         return new Builder()
                 .setId(r.mId)
diff --git a/src/com/android/tv/dvr/provider/AsyncDvrDbTask.java b/src/com/android/tv/dvr/provider/AsyncDvrDbTask.java
index 1a12fb2..c5383d0 100644
--- a/src/com/android/tv/dvr/provider/AsyncDvrDbTask.java
+++ b/src/com/android/tv/dvr/provider/AsyncDvrDbTask.java
@@ -21,8 +21,8 @@
 import android.os.AsyncTask;
 import android.support.annotation.Nullable;
 
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.dvr.provider.DvrContract.Schedules;
 import com.android.tv.dvr.provider.DvrContract.SeriesRecordings;
 import com.android.tv.util.NamedThreadFactory;
diff --git a/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java b/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
index 2f16ba5..8b9481a 100644
--- a/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
+++ b/src/com/android/tv/dvr/provider/DvrDatabaseHelper.java
@@ -27,8 +27,8 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.dvr.provider.DvrContract.Schedules;
 import com.android.tv.dvr.provider.DvrContract.SeriesRecordings;
 
diff --git a/src/com/android/tv/dvr/DvrDbSync.java b/src/com/android/tv/dvr/provider/DvrDbSync.java
similarity index 90%
rename from src/com/android/tv/dvr/DvrDbSync.java
rename to src/com/android/tv/dvr/provider/DvrDbSync.java
index df18145..ff39195 100644
--- a/src/com/android/tv/dvr/DvrDbSync.java
+++ b/src/com/android/tv/dvr/provider/DvrDbSync.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.provider;
 
 import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
@@ -34,8 +34,13 @@
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
+import com.android.tv.dvr.DvrDataManagerImpl;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
 import com.android.tv.util.AsyncDbTask.AsyncQueryProgramTask;
-import com.android.tv.util.TvProviderUriMatcher;
+import com.android.tv.util.TvUriMatcher;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -57,11 +62,12 @@
  */
 @MainThread
 @TargetApi(Build.VERSION_CODES.N)
-class DvrDbSync {
+public class DvrDbSync {
     private static final String TAG = "DvrDbSync";
     private static final boolean DEBUG = false;
 
     private final Context mContext;
+    private final DvrManager mDvrManager;
     private final DvrDataManagerImpl mDataManager;
     private final ChannelDataManager mChannelDataManager;
     private final Queue<Long> mProgramIdQueue = new LinkedList<>();
@@ -72,12 +78,12 @@
         @SuppressLint("SwitchIntDef")
         @Override
         public void onChange(boolean selfChange, Uri uri) {
-            switch (TvProviderUriMatcher.match(uri)) {
-                case TvProviderUriMatcher.MATCH_PROGRAM:
+            switch (TvUriMatcher.match(uri)) {
+                case TvUriMatcher.MATCH_PROGRAM:
                     if (DEBUG) Log.d(TAG, "onProgramsUpdated");
                     onProgramsUpdated();
                     break;
-                case TvProviderUriMatcher.MATCH_PROGRAM_ID:
+                case TvUriMatcher.MATCH_PROGRAM_ID:
                     if (DEBUG) {
                         Log.d(TAG, "onProgramUpdated: programId=" + ContentUris.parseId(uri));
                     }
@@ -129,17 +135,21 @@
         }
     };
 
-    DvrDbSync(Context context, DvrDataManagerImpl dataManager) {
-        this(context, dataManager, TvApplication.getSingletons(context).getChannelDataManager());
+    public DvrDbSync(Context context, DvrDataManagerImpl dataManager) {
+        this(context, dataManager, TvApplication.getSingletons(context).getChannelDataManager(),
+                TvApplication.getSingletons(context).getDvrManager(),
+                SeriesRecordingScheduler.getInstance(context));
     }
 
     @VisibleForTesting
     DvrDbSync(Context context, DvrDataManagerImpl dataManager,
-            ChannelDataManager channelDataManager) {
+            ChannelDataManager channelDataManager, DvrManager dvrManager,
+            SeriesRecordingScheduler seriesRecordingScheduler) {
         mContext = context;
+        mDvrManager = dvrManager;
         mDataManager = dataManager;
         mChannelDataManager = channelDataManager;
-        mSeriesRecordingScheduler = SeriesRecordingScheduler.getInstance(context);
+        mSeriesRecordingScheduler = seriesRecordingScheduler;
     }
 
     /**
@@ -273,16 +283,15 @@
                 // Check the series recording.
                 SeriesRecording seriesRecordingForOldSchedule =
                         mDataManager.getSeriesRecording(schedule.getSeriesRecordingId());
-                if (program.getSeriesId() != null) {
+                if (program.isEpisodic()) {
                     // New program belongs to a series.
                     SeriesRecording seriesRecording =
                             mDataManager.getSeriesRecording(program.getSeriesId());
                     if (seriesRecording == null) {
                         // The new program is episodic while the previous one isn't.
-                        SeriesRecording newSeriesRecording = TvApplication.getSingletons(mContext)
-                                .getDvrManager().addSeriesRecording(program,
-                                        Collections.singletonList(program),
-                                        SeriesRecording.STATE_SERIES_STOPPED);
+                        SeriesRecording newSeriesRecording = mDvrManager.addSeriesRecording(
+                                program, Collections.singletonList(program),
+                                SeriesRecording.STATE_SERIES_STOPPED);
                         builder.setSeriesRecordingId(newSeriesRecording.getId());
                         needUpdate = true;
                     } else if (seriesRecording.getId() != schedule.getSeriesRecordingId()) {
@@ -306,8 +315,9 @@
                     // Old program belongs to a series but the new one doesn't.
                     seriesRecordingsToUpdate.add(seriesRecordingForOldSchedule);
                 }
-                // Change start time only when the recording start time has not passed.
-                boolean needToChangeStartTime = schedule.getStartTimeMs() > currentTimeMs
+                // Change start time only when the recording is not started yet.
+                boolean needToChangeStartTime =
+                        schedule.getState() != ScheduledRecording.STATE_RECORDING_IN_PROGRESS
                         && program.getStartTimeUtcMillis() != schedule.getStartTimeMs();
                 if (needToChangeStartTime) {
                     builder.setStartTimeMs(program.getStartTimeUtcMillis());
diff --git a/src/com/android/tv/dvr/EpisodicProgramLoadTask.java b/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
similarity index 82%
rename from src/com/android/tv/dvr/EpisodicProgramLoadTask.java
rename to src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
index 15ca270..ba0aca5 100644
--- a/src/com/android/tv/dvr/EpisodicProgramLoadTask.java
+++ b/src/com/android/tv/dvr/provider/EpisodicProgramLoadTask.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.provider;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -24,13 +24,15 @@
 import android.net.Uri;
 import android.os.Build;
 import android.support.annotation.Nullable;
-import android.support.annotation.VisibleForTesting;
 import android.support.annotation.WorkerThread;
-import android.text.TextUtils;
 
 import com.android.tv.TvApplication;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Program;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.data.SeasonEpisodeNumber;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.util.AsyncDbTask.AsyncProgramQueryTask;
 import com.android.tv.util.AsyncDbTask.CursorFilter;
 import com.android.tv.util.PermissionUtils;
@@ -40,7 +42,6 @@
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -253,21 +254,13 @@
         return sqlParams;
     }
 
-    @VisibleForTesting
-    static boolean isEpisodeScheduled(Collection<ScheduledEpisode> scheduledEpisodes,
-            ScheduledEpisode episode) {
-        // The episode whose season number or episode number is null will always be scheduled.
-        return scheduledEpisodes.contains(episode) && !TextUtils.isEmpty(episode.seasonNumber)
-                && !TextUtils.isEmpty(episode.episodeNumber);
-    }
-
     /**
      * Filter the programs which match the series recording. The episodes which the schedules are
      * already created for are filtered out too.
      */
     private class SeriesRecordingCursorFilter implements CursorFilter {
         private final Set<Long> mDisallowedProgramIds = new HashSet<>();
-        private final Set<ScheduledEpisode> mScheduledEpisodes = new HashSet<>();
+        private final Set<SeasonEpisodeNumber> mSeasonEpisodeNumbers = new HashSet<>();
 
         SeriesRecordingCursorFilter(List<SeriesRecording> seriesRecordings) {
             if (!mLoadDisallowedProgram) {
@@ -282,7 +275,7 @@
                     if (seriesRecordingIds.contains(r.getSeriesRecordingId())
                             && r.getState() != ScheduledRecording.STATE_RECORDING_FAILED
                             && r.getState() != ScheduledRecording.STATE_RECORDING_CLIPPED) {
-                        mScheduledEpisodes.add(new ScheduledEpisode(r));
+                        mSeasonEpisodeNumbers.add(new SeasonEpisodeNumber(r));
                     }
                 }
             }
@@ -306,9 +299,9 @@
                 }
                 if (programMatches) {
                     return mLoadScheduledEpisode
-                            || !isEpisodeScheduled(mScheduledEpisodes, new ScheduledEpisode(
-                                    seriesRecording.getId(), program.getSeasonNumber(),
-                                    program.getEpisodeNumber()));
+                            || !mSeasonEpisodeNumbers.contains(new SeasonEpisodeNumber(
+                            seriesRecording.getId(), program.getSeasonNumber(),
+                            program.getEpisodeNumber()));
                 }
             }
             return false;
@@ -333,50 +326,4 @@
         public String[] selectionArgs;
         public CursorFilter filter;
     }
-
-    /**
-     * A plain java object which includes the season/episode number for the series recording.
-     */
-    public static class ScheduledEpisode {
-        public final long seriesRecordingId;
-        public final String seasonNumber;
-        public final String episodeNumber;
-
-        /**
-         * Create a new Builder with the values set from an existing {@link ScheduledRecording}.
-         */
-        ScheduledEpisode(ScheduledRecording r) {
-            this(r.getSeriesRecordingId(), r.getSeasonNumber(), r.getEpisodeNumber());
-        }
-
-        public ScheduledEpisode(long seriesRecordingId, String seasonNumber, String episodeNumber) {
-            this.seriesRecordingId = seriesRecordingId;
-            this.seasonNumber = seasonNumber;
-            this.episodeNumber = episodeNumber;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (!(o instanceof ScheduledEpisode)) return false;
-            ScheduledEpisode that = (ScheduledEpisode) o;
-            return seriesRecordingId == that.seriesRecordingId
-                    && Objects.equals(seasonNumber, that.seasonNumber)
-                    && Objects.equals(episodeNumber, that.episodeNumber);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(seriesRecordingId, seasonNumber, episodeNumber);
-        }
-
-        @Override
-        public String toString() {
-            return "ScheduledEpisode{" +
-                    "seriesRecordingId=" + seriesRecordingId +
-                    ", seasonNumber='" + seasonNumber +
-                    ", episodeNumber=" + episodeNumber +
-                    '}';
-        }
-    }
 }
diff --git a/src/com/android/tv/dvr/ConflictChecker.java b/src/com/android/tv/dvr/recorder/ConflictChecker.java
similarity index 98%
rename from src/com/android/tv/dvr/ConflictChecker.java
rename to src/com/android/tv/dvr/recorder/ConflictChecker.java
index 201e379..8aa9011 100644
--- a/src/com/android/tv/dvr/ConflictChecker.java
+++ b/src/com/android/tv/dvr/recorder/ConflictChecker.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
 import android.annotation.TargetApi;
 import android.content.ContentUris;
@@ -37,6 +37,9 @@
 import com.android.tv.data.Channel;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
+import com.android.tv.dvr.DvrScheduleManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.ui.DvrUiHelper;
 
 import java.util.ArrayList;
 import java.util.HashMap;
diff --git a/src/com/android/tv/dvr/recorder/DvrRecordingService.java b/src/com/android/tv/dvr/recorder/DvrRecordingService.java
new file mode 100644
index 0000000..5d324ca
--- /dev/null
+++ b/src/com/android/tv/dvr/recorder/DvrRecordingService.java
@@ -0,0 +1,207 @@
+/*
+ * 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.dvr.recorder;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Build;
+import android.os.IBinder;
+import android.support.annotation.MainThread;
+import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.VisibleForTesting;
+import android.util.Log;
+
+import com.android.tv.ApplicationSingletons;
+import com.android.tv.InputSessionManager;
+import com.android.tv.InputSessionManager.OnRecordingSessionChangeListener;
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.dvr.WritableDvrDataManager;
+import com.android.tv.util.Clock;
+import com.android.tv.util.RecurringRunner;
+
+/**
+ * DVR recording service. This service should be a foreground service and send a notification
+ * to users to do long-running recording task.
+ *
+ * <p>This service is waken up when there's a scheduled recording coming soon and at boot completed
+ * since schedules have to be loaded from databases in order to set new recording alarms, which
+ * might take a long time.
+ */
+@RequiresApi(Build.VERSION_CODES.N)
+public class DvrRecordingService extends Service {
+    private static final String TAG = "DvrRecordingService";
+    private static final boolean DEBUG = false;
+
+    private static final String DVR_NOTIFICATION_CHANNEL_ID = "dvr_notification_channel";
+    private static final int ONGOING_NOTIFICATION_ID = 1;
+    @VisibleForTesting static final String EXTRA_START_FOR_RECORDING = "start_for_recording";
+
+    private static DvrRecordingService sInstance;
+    private NotificationChannel mNotificationChannel;
+    private String mContentTitle;
+    private String mContentTextRecording;
+    private String mContentTextLoading;
+
+    /**
+     * Starts the service in foreground.
+     *
+     * @param startForRecording {@code true} if there are upcoming recordings in
+     *                          {@link RecordingScheduler#SOON_DURATION_IN_MS} and the service is
+     *                          started in foreground for those recordings.
+     */
+    @MainThread
+    static void startForegroundService(Context context, boolean startForRecording) {
+        if (sInstance == null) {
+            Intent intent = new Intent(context, DvrRecordingService.class);
+            intent.putExtra(EXTRA_START_FOR_RECORDING, startForRecording);
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+                context.startForegroundService(intent);
+            } else {
+                context.startService(intent);
+            }
+        } else {
+            sInstance.startForeground(startForRecording);
+        }
+    }
+
+    @MainThread
+    static void stopForegroundIfNotRecording() {
+        if (sInstance != null) {
+            sInstance.stopForegroundIfNotRecordingInternal();
+        }
+    }
+
+    private RecurringRunner mReaperRunner;
+    private InputSessionManager mSessionManager;
+
+    @VisibleForTesting boolean mIsRecording;
+    private boolean mForeground;
+
+    @VisibleForTesting final OnRecordingSessionChangeListener mOnRecordingSessionChangeListener =
+            new OnRecordingSessionChangeListener() {
+                @Override
+                public void onRecordingSessionChange(final boolean create, final int count) {
+                    mIsRecording = count > 0;
+                    if (create) {
+                        startForeground(true);
+                    } else {
+                        stopForegroundIfNotRecordingInternal();
+                    }
+                }
+            };
+
+    @Override
+    public void onCreate() {
+        TvApplication.setCurrentRunningProcess(this, true);
+        if (DEBUG) Log.d(TAG, "onCreate");
+        super.onCreate();
+        SoftPreconditions.checkFeatureEnabled(this, CommonFeatures.DVR, TAG);
+        sInstance = this;
+        ApplicationSingletons singletons = TvApplication.getSingletons(this);
+        WritableDvrDataManager dataManager =
+                (WritableDvrDataManager) singletons.getDvrDataManager();
+        mSessionManager = singletons.getInputSessionManager();
+        mSessionManager.addOnRecordingSessionChangeListener(mOnRecordingSessionChangeListener);
+        mReaperRunner = new RecurringRunner(this, java.util.concurrent.TimeUnit.DAYS.toMillis(1),
+                new ScheduledProgramReaper(dataManager, Clock.SYSTEM), null);
+        mReaperRunner.start();
+        mContentTitle = getString(R.string.dvr_notification_content_title);
+        mContentTextRecording = getString(R.string.dvr_notification_content_text_recording);
+        mContentTextLoading = getString(R.string.dvr_notification_content_text_loading);
+        createNotificationChannel();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (DEBUG) Log.d(TAG, "onStartCommand (" + intent + "," + flags + "," + startId + ")");
+        if (intent != null) {
+            startForeground(intent.getBooleanExtra(EXTRA_START_FOR_RECORDING, false));
+        }
+        return START_STICKY;
+    }
+
+    @Override
+    public void onDestroy() {
+        if (DEBUG) Log.d(TAG, "onDestroy");
+        mReaperRunner.stop();
+        mSessionManager.removeRecordingSessionChangeListener(mOnRecordingSessionChangeListener);
+        sInstance = null;
+        super.onDestroy();
+    }
+
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @VisibleForTesting
+    protected void stopForegroundIfNotRecordingInternal() {
+        if (mForeground && !mIsRecording) {
+            stopForeground();
+        }
+    }
+
+    private void startForeground(boolean hasUpcomingRecording) {
+        if (!mForeground || hasUpcomingRecording) {
+            // We may need to update notification for upcoming recordings.
+            mForeground = true;
+            startForegroundInternal(hasUpcomingRecording);
+        }
+    }
+
+    private void stopForeground() {
+        stopForegroundInternal();
+        mForeground = false;
+    }
+
+    @VisibleForTesting
+    protected void startForegroundInternal(boolean hasUpcomingRecording) {
+        // STOPSHIP: Replace the content title with real UX strings
+        Notification.Builder builder = new Notification.Builder(this)
+                .setContentTitle(mContentTitle)
+                .setContentText(hasUpcomingRecording ? mContentTextRecording : mContentTextLoading)
+                .setSmallIcon(R.drawable.ic_dvr);
+        Notification notification = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O ?
+                builder.setChannelId(DVR_NOTIFICATION_CHANNEL_ID).build() : builder.build();
+        startForeground(ONGOING_NOTIFICATION_ID, notification);
+    }
+
+    @VisibleForTesting
+    protected void stopForegroundInternal() {
+        stopForeground(true);
+    }
+
+    private void createNotificationChannel() {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            // STOPSHIP: Replace the channel name with real UX strings
+            mNotificationChannel = new NotificationChannel(DVR_NOTIFICATION_CHANNEL_ID,
+                    getString(R.string.dvr_notification_channel_name),
+                    NotificationManager.IMPORTANCE_LOW);
+            ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE))
+                    .createNotificationChannel(mNotificationChannel);
+        }
+    }
+}
diff --git a/src/com/android/tv/dvr/DvrStartRecordingReceiver.java b/src/com/android/tv/dvr/recorder/DvrStartRecordingReceiver.java
similarity index 75%
rename from src/com/android/tv/dvr/DvrStartRecordingReceiver.java
rename to src/com/android/tv/dvr/recorder/DvrStartRecordingReceiver.java
index 6d2f0d4..f1c0020 100644
--- a/src/com/android/tv/dvr/DvrStartRecordingReceiver.java
+++ b/src/com/android/tv/dvr/recorder/DvrStartRecordingReceiver.java
@@ -14,21 +14,27 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
-
-import com.android.tv.TvApplication;
+package com.android.tv.dvr.recorder;
 
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+
+import com.android.tv.TvApplication;
 
 /**
  * Signals the DVR to start recording shows <i>soon</i>.
  */
+@RequiresApi(Build.VERSION_CODES.N)
 public class DvrStartRecordingReceiver extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
         TvApplication.setCurrentRunningProcess(context, true);
-        DvrRecordingService.startService(context);
+        RecordingScheduler scheduler = TvApplication.getSingletons(context).getRecordingScheduler();
+        if (scheduler != null) {
+            scheduler.updateAndStartServiceIfNeeded();
+        }
     }
 }
diff --git a/src/com/android/tv/dvr/InputTaskScheduler.java b/src/com/android/tv/dvr/recorder/InputTaskScheduler.java
similarity index 96%
rename from src/com/android/tv/dvr/InputTaskScheduler.java
rename to src/com/android/tv/dvr/recorder/InputTaskScheduler.java
index 53c89eb..fee4568 100644
--- a/src/com/android/tv/dvr/InputTaskScheduler.java
+++ b/src/com/android/tv/dvr/recorder/InputTaskScheduler.java
@@ -14,14 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
 import android.content.Context;
 import android.media.tv.TvInputInfo;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -30,6 +29,10 @@
 import com.android.tv.InputSessionManager;
 import com.android.tv.data.Channel;
 import com.android.tv.data.ChannelDataManager;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.WritableDvrDataManager;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.util.Clock;
 import com.android.tv.util.CompositeComparator;
 
@@ -121,14 +124,13 @@
             ChannelDataManager channelDataManager, DvrManager dvrManager,
             DvrDataManager dataManager, InputSessionManager sessionManager, Clock clock) {
         this(context, input, looper, channelDataManager, dvrManager, dataManager, sessionManager,
-                clock, new Handler(Looper.getMainLooper()), null, null);
+                clock, null);
     }
 
     @VisibleForTesting
     InputTaskScheduler(Context context, TvInputInfo input, Looper looper,
             ChannelDataManager channelDataManager, DvrManager dvrManager,
             DvrDataManager dataManager, InputSessionManager sessionManager, Clock clock,
-            Handler mainThreadHandler, @Nullable Handler workerThreadHandler,
             RecordingTaskFactory recordingTaskFactory) {
         if (DEBUG) Log.d(TAG, "Creating scheduler for " + input);
         mContext = context;
@@ -139,7 +141,7 @@
         mDataManager = (WritableDvrDataManager) dataManager;
         mSessionManager = sessionManager;
         mClock = clock;
-        mMainThreadHandler = mainThreadHandler;
+        mMainThreadHandler = new Handler(Looper.getMainLooper());
         mRecordingTaskFactory = recordingTaskFactory != null ? recordingTaskFactory
                 : new RecordingTaskFactory() {
             @Override
@@ -150,11 +152,7 @@
                         mDataManager, mClock);
             }
         };
-        if (workerThreadHandler == null) {
-            mHandler = new WorkerThreadHandler(looper);
-        } else {
-            mHandler = workerThreadHandler;
-        }
+        mHandler = new WorkerThreadHandler(looper);
     }
 
     /**
@@ -211,7 +209,7 @@
                     && schedule.getStartTimeMs() > wrapper.mTask.getStartTimeMs()) {
                 // It shouldn't have started. Cancel and put to the waiting list.
                 // The schedules will be rebuilt when the task is removed.
-                // The reschedule is called in Scheduler.
+                // The reschedule is called in RecordingScheduler.
                 wrapper.mTask.cancel();
                 mWaitingSchedules.put(schedule.getId(), schedule);
                 return;
diff --git a/src/com/android/tv/dvr/recorder/RecordingScheduler.java b/src/com/android/tv/dvr/recorder/RecordingScheduler.java
new file mode 100644
index 0000000..cbaf46b
--- /dev/null
+++ b/src/com/android/tv/dvr/recorder/RecordingScheduler.java
@@ -0,0 +1,329 @@
+/*
+ * 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.dvr.recorder;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager.TvInputCallback;
+import android.os.Build;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.support.annotation.MainThread;
+import android.support.annotation.RequiresApi;
+import android.support.annotation.VisibleForTesting;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.Range;
+
+import com.android.tv.ApplicationSingletons;
+import com.android.tv.InputSessionManager;
+import com.android.tv.TvApplication;
+import com.android.tv.common.SoftPreconditions;
+import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.ChannelDataManager.Listener;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
+import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.WritableDvrDataManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.util.Clock;
+import com.android.tv.util.TvInputManagerHelper;
+import com.android.tv.util.Utils;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * The core class to manage DVR schedule and run recording task.
+ **
+ * <p> This class is responsible for:
+ * <ul>
+ *     <li>Sending record commands to TV inputs</li>
+ *     <li>Resolving conflicting schedules, handling overlapping recording time durations, etc.</li>
+ * </ul>
+ *
+ * <p>This should be a singleton associated with application's main process.
+ */
+@RequiresApi(Build.VERSION_CODES.N)
+@MainThread
+public class RecordingScheduler extends TvInputCallback implements ScheduledRecordingListener {
+    private static final String TAG = "RecordingScheduler";
+    private static final boolean DEBUG = false;
+
+    private static final String HANDLER_THREAD_NAME = "RecordingScheduler";
+    private final static long SOON_DURATION_IN_MS = TimeUnit.MINUTES.toMillis(1);
+    @VisibleForTesting final static long MS_TO_WAKE_BEFORE_START = TimeUnit.SECONDS.toMillis(30);
+
+    private final Looper mLooper;
+    private final InputSessionManager mSessionManager;
+    private final WritableDvrDataManager mDataManager;
+    private final DvrManager mDvrManager;
+    private final ChannelDataManager mChannelDataManager;
+    private final TvInputManagerHelper mInputManager;
+    private final Context mContext;
+    private final Clock mClock;
+    private final AlarmManager mAlarmManager;
+
+    private final Map<String, InputTaskScheduler> mInputSchedulerMap = new ArrayMap<>();
+    private long mLastStartTimePendingMs;
+
+    private OnDvrScheduleLoadFinishedListener mDvrScheduleLoadListener =
+            new OnDvrScheduleLoadFinishedListener() {
+                @Override
+                public void onDvrScheduleLoadFinished() {
+                    mDataManager.removeDvrScheduleLoadFinishedListener(this);
+                    if (isDbLoaded()) {
+                        updateInternal();
+                    }
+                }
+            };
+
+    private Listener mChannelDataLoadListener = new Listener() {
+        @Override
+        public void onLoadFinished() {
+            mChannelDataManager.removeListener(this);
+            if (isDbLoaded()) {
+                updateInternal();
+            }
+        }
+
+        @Override
+        public void onChannelListUpdated() { }
+
+        @Override
+        public void onChannelBrowsableChanged() { }
+    };
+
+    /**
+     * Creates a scheduler to schedule alarms for scheduled recordings and create recording tasks.
+     * This method should be only called once in the life-cycle of the application.
+     */
+    public static RecordingScheduler createScheduler(Context context) {
+        SoftPreconditions.checkState(
+                TvApplication.getSingletons(context).getRecordingScheduler() == null);
+        HandlerThread handlerThread = new HandlerThread(HANDLER_THREAD_NAME);
+        handlerThread.start();
+        ApplicationSingletons singletons = TvApplication.getSingletons(context);
+        return new RecordingScheduler(handlerThread.getLooper(),
+                singletons.getDvrManager(), singletons.getInputSessionManager(),
+                (WritableDvrDataManager) singletons.getDvrDataManager(),
+                singletons.getChannelDataManager(), singletons.getTvInputManagerHelper(), context,
+                Clock.SYSTEM, (AlarmManager) context.getSystemService(Context.ALARM_SERVICE));
+    }
+
+    @VisibleForTesting
+    RecordingScheduler(Looper looper, DvrManager dvrManager, InputSessionManager sessionManager,
+            WritableDvrDataManager dataManager, ChannelDataManager channelDataManager,
+            TvInputManagerHelper inputManager, Context context, Clock clock,
+            AlarmManager alarmManager) {
+        mLooper = looper;
+        mDvrManager = dvrManager;
+        mSessionManager = sessionManager;
+        mDataManager = dataManager;
+        mChannelDataManager = channelDataManager;
+        mInputManager = inputManager;
+        mContext = context;
+        mClock = clock;
+        mAlarmManager = alarmManager;
+        mDataManager.addScheduledRecordingListener(this);
+        mInputManager.addCallback(this);
+        if (isDbLoaded()) {
+            updateInternal();
+        } else {
+            if (!mDataManager.isDvrScheduleLoadFinished()) {
+                mDataManager.addDvrScheduleLoadFinishedListener(mDvrScheduleLoadListener);
+            }
+            if (!mChannelDataManager.isDbLoadFinished()) {
+                mChannelDataManager.addListener(mChannelDataLoadListener);
+            }
+        }
+    }
+
+    /**
+     * Start recording that will happen soon, and set the next alarm time.
+     */
+    public void updateAndStartServiceIfNeeded() {
+        if (DEBUG) Log.d(TAG, "update and start service if needed");
+        if (isDbLoaded()) {
+            updateInternal();
+        } else {
+            // updateInternal will be called when DB is loaded. Start DvrRecordingService to
+            // prevent process being killed before that.
+            DvrRecordingService.startForegroundService(mContext, false);
+        }
+    }
+
+    private void updateInternal() {
+        boolean recordingSoon = updatePendingRecordings();
+        updateNextAlarm();
+        if (recordingSoon) {
+            // Start DvrRecordingService to protect upcoming recording task from being killed.
+            DvrRecordingService.startForegroundService(mContext, true);
+        } else {
+            DvrRecordingService.stopForegroundIfNotRecording();
+        }
+    }
+
+    private boolean updatePendingRecordings() {
+        List<ScheduledRecording> scheduledRecordings = mDataManager
+                .getScheduledRecordings(new Range<>(mLastStartTimePendingMs,
+                                mClock.currentTimeMillis() + SOON_DURATION_IN_MS),
+                        ScheduledRecording.STATE_RECORDING_NOT_STARTED);
+        for (ScheduledRecording r : scheduledRecordings) {
+            scheduleRecordingSoon(r);
+        }
+        // update() may be called multiple times, under this situation, pending recordings may be
+        // already updated thus scheduledRecordings may have a size of 0. Therefore we also have to
+        // check mLastStartTimePendingMs to check if we have upcoming recordings and prevent the
+        // recording service being wrongly pushed back to background in updateInternal().
+        return scheduledRecordings.size() > 0
+                || (mLastStartTimePendingMs > mClock.currentTimeMillis()
+                && mLastStartTimePendingMs < mClock.currentTimeMillis() + SOON_DURATION_IN_MS);
+    }
+
+    private boolean isDbLoaded() {
+        return mDataManager.isDvrScheduleLoadFinished() && mChannelDataManager.isDbLoadFinished();
+    }
+
+    @Override
+    public void onScheduledRecordingAdded(ScheduledRecording... schedules) {
+        if (DEBUG) Log.d(TAG, "added " + Arrays.asList(schedules));
+        if (!isDbLoaded()) {
+            return;
+        }
+        handleScheduleChange(schedules);
+    }
+
+    @Override
+    public void onScheduledRecordingRemoved(ScheduledRecording... schedules) {
+        if (DEBUG) Log.d(TAG, "removed " + Arrays.asList(schedules));
+        if (!isDbLoaded()) {
+            return;
+        }
+        boolean needToUpdateAlarm = false;
+        for (ScheduledRecording schedule : schedules) {
+            InputTaskScheduler inputTaskScheduler = mInputSchedulerMap.get(schedule.getInputId());
+            if (inputTaskScheduler != null) {
+                inputTaskScheduler.removeSchedule(schedule);
+                needToUpdateAlarm = true;
+            }
+        }
+        if (needToUpdateAlarm) {
+            updateNextAlarm();
+        }
+    }
+
+    @Override
+    public void onScheduledRecordingStatusChanged(ScheduledRecording... schedules) {
+        if (DEBUG) Log.d(TAG, "state changed " + Arrays.asList(schedules));
+        if (!isDbLoaded()) {
+            return;
+        }
+        // Update the recordings.
+        for (ScheduledRecording schedule : schedules) {
+            InputTaskScheduler inputTaskScheduler = mInputSchedulerMap.get(schedule.getInputId());
+            if (inputTaskScheduler != null) {
+                inputTaskScheduler.updateSchedule(schedule);
+            }
+        }
+        handleScheduleChange(schedules);
+    }
+
+    private void handleScheduleChange(ScheduledRecording... schedules) {
+        boolean needToUpdateAlarm = false;
+        for (ScheduledRecording schedule : schedules) {
+            if (schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED) {
+                if (startsWithin(schedule, SOON_DURATION_IN_MS)) {
+                    scheduleRecordingSoon(schedule);
+                } else {
+                    needToUpdateAlarm = true;
+                }
+            }
+        }
+        if (needToUpdateAlarm) {
+            updateNextAlarm();
+        }
+    }
+
+    private void scheduleRecordingSoon(ScheduledRecording schedule) {
+        TvInputInfo input = Utils.getTvInputInfoForInputId(mContext, schedule.getInputId());
+        if (input == null) {
+            Log.e(TAG, "Can't find input for " + schedule);
+            mDataManager.changeState(schedule, ScheduledRecording.STATE_RECORDING_FAILED);
+            return;
+        }
+        if (!input.canRecord() || input.getTunerCount() <= 0) {
+            Log.e(TAG, "TV input doesn't support recording: " + input);
+            mDataManager.changeState(schedule, ScheduledRecording.STATE_RECORDING_FAILED);
+            return;
+        }
+        InputTaskScheduler inputTaskScheduler = mInputSchedulerMap.get(input.getId());
+        if (inputTaskScheduler == null) {
+            inputTaskScheduler = new InputTaskScheduler(mContext, input, mLooper,
+                    mChannelDataManager, mDvrManager, mDataManager, mSessionManager, mClock);
+            mInputSchedulerMap.put(input.getId(), inputTaskScheduler);
+        }
+        inputTaskScheduler.addSchedule(schedule);
+        if (mLastStartTimePendingMs < schedule.getStartTimeMs()) {
+            mLastStartTimePendingMs = schedule.getStartTimeMs();
+        }
+    }
+
+    private void updateNextAlarm() {
+        long nextStartTime = mDataManager.getNextScheduledStartTimeAfter(
+                Math.max(mLastStartTimePendingMs, mClock.currentTimeMillis()));
+        if (nextStartTime != DvrDataManager.NEXT_START_TIME_NOT_FOUND) {
+            long wakeAt = nextStartTime - MS_TO_WAKE_BEFORE_START;
+            if (DEBUG) Log.d(TAG, "Set alarm to record at " + wakeAt);
+            Intent intent = new Intent(mContext, DvrStartRecordingReceiver.class);
+            PendingIntent alarmIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+            // This will cancel the previous alarm.
+            mAlarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, wakeAt, alarmIntent);
+        } else {
+            if (DEBUG) Log.d(TAG, "No future recording, alarm not set");
+        }
+    }
+
+    @VisibleForTesting
+    boolean startsWithin(ScheduledRecording scheduledRecording, long durationInMs) {
+        return mClock.currentTimeMillis() >= scheduledRecording.getStartTimeMs() - durationInMs;
+    }
+
+    // No need to remove input task schedule worker when the input is removed. If the input is
+    // removed temporarily, the scheduler should keep the non-started schedules.
+    @Override
+    public void onInputUpdated(String inputId) {
+        InputTaskScheduler inputTaskScheduler = mInputSchedulerMap.get(inputId);
+        if (inputTaskScheduler != null) {
+            inputTaskScheduler.updateTvInputInfo(Utils.getTvInputInfoForInputId(mContext, inputId));
+        }
+    }
+
+    @Override
+    public void onTvInputInfoUpdated(TvInputInfo input) {
+        InputTaskScheduler inputTaskScheduler = mInputSchedulerMap.get(input.getId());
+        if (inputTaskScheduler != null) {
+            inputTaskScheduler.updateTvInputInfo(input);
+        }
+    }
+}
diff --git a/src/com/android/tv/dvr/RecordingTask.java b/src/com/android/tv/dvr/recorder/RecordingTask.java
similarity index 93%
rename from src/com/android/tv/dvr/RecordingTask.java
rename to src/com/android/tv/dvr/recorder/RecordingTask.java
index c3d236b..1488805 100644
--- a/src/com/android/tv/dvr/RecordingTask.java
+++ b/src/com/android/tv/dvr/recorder/RecordingTask.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -37,7 +37,10 @@
 import com.android.tv.TvApplication;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
-import com.android.tv.dvr.InputTaskScheduler.HandlerWrapper;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.WritableDvrDataManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.recorder.InputTaskScheduler.HandlerWrapper;
 import com.android.tv.util.Clock;
 import com.android.tv.util.Utils;
 
@@ -51,7 +54,6 @@
  * There is only one looper so messages must be handled quickly or start a separate thread.
  */
 @WorkerThread
-@VisibleForTesting
 @TargetApi(Build.VERSION_CODES.N)
 public class RecordingTask extends RecordingCallback implements Handler.Callback,
         DvrManager.Listener {
@@ -256,13 +258,21 @@
                     public void run() {
                         if (TvApplication.getSingletons(mContext).getMainActivityWrapper()
                                 .isResumed()) {
-                            Toast.makeText(mContext.getApplicationContext(),
-                                    R.string.dvr_error_insufficient_space_description,
-                                    Toast.LENGTH_LONG)
-                                    .show();
+                            ScheduledRecording scheduledRecording = mDataManager
+                                    .getScheduledRecording(mScheduledRecording.getId());
+                            if (scheduledRecording != null) {
+                                Toast.makeText(mContext.getApplicationContext(),
+                                        mContext.getString(R.string
+                                        .dvr_error_insufficient_space_description_one_recording,
+                                        scheduledRecording.getProgramDisplayTitle(mContext)),
+                                        Toast.LENGTH_LONG)
+                                        .show();
+                            }
                         } else {
                             Utils.setRecordingFailedReason(mContext.getApplicationContext(),
                                     TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE);
+                            Utils.addFailedScheduledRecordingInfo(mContext.getApplicationContext(),
+                                    mScheduledRecording.getProgramDisplayTitle(mContext));
                         }
                     }
                 });
diff --git a/src/com/android/tv/dvr/ScheduledProgramReaper.java b/src/com/android/tv/dvr/recorder/ScheduledProgramReaper.java
similarity index 92%
rename from src/com/android/tv/dvr/ScheduledProgramReaper.java
rename to src/com/android/tv/dvr/recorder/ScheduledProgramReaper.java
index cd79a63..d958c4a 100644
--- a/src/com/android/tv/dvr/ScheduledProgramReaper.java
+++ b/src/com/android/tv/dvr/recorder/ScheduledProgramReaper.java
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
 import android.support.annotation.MainThread;
 import android.support.annotation.VisibleForTesting;
 
+import com.android.tv.dvr.WritableDvrDataManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.util.Clock;
 
 import java.util.ArrayList;
diff --git a/src/com/android/tv/dvr/SeriesRecordingScheduler.java b/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
similarity index 90%
rename from src/com/android/tv/dvr/SeriesRecordingScheduler.java
rename to src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
index 5ed12ce..15508c2 100644
--- a/src/com/android/tv/dvr/SeriesRecordingScheduler.java
+++ b/src/com/android/tv/dvr/recorder/SeriesRecordingScheduler.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
 import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
@@ -23,7 +23,6 @@
 import android.os.AsyncTask;
 import android.os.Build;
 import android.support.annotation.MainThread;
-import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
@@ -36,11 +35,19 @@
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Program;
 import com.android.tv.data.epg.EpgFetcher;
+import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
 import com.android.tv.dvr.DvrDataManager.SeriesRecordingListener;
-import com.android.tv.dvr.EpisodicProgramLoadTask.ScheduledEpisode;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.WritableDvrDataManager;
+import com.android.tv.dvr.data.SeasonEpisodeNumber;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesInfo;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
 import com.android.tv.experiments.Experiments;
 
+import com.android.tv.util.LocationUtils;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -52,11 +59,11 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.Set;
 
 /**
- * Creates the {@link ScheduledRecording}s for the {@link SeriesRecording}.
+ * Creates the {@link com.android.tv.dvr.data.ScheduledRecording}s for
+ * the {@link com.android.tv.dvr.data.SeriesRecording}.
  * <p>
  * The current implementation assumes that the series recordings are scheduled only for one channel.
  */
@@ -85,15 +92,13 @@
     private final DvrManager mDvrManager;
     private final WritableDvrDataManager mDataManager;
     private final List<SeriesRecordingUpdateTask> mScheduleTasks = new ArrayList<>();
-    private final List<FetchSeriesInfoTask> mFetchSeriesInfoTasks = new ArrayList<>();
+    private final LongSparseArray<FetchSeriesInfoTask> mFetchSeriesInfoTasks =
+            new LongSparseArray<>();
     private final Set<String> mFetchedSeriesIds = new ArraySet<>();
     private final SharedPreferences mSharedPreferences;
     private boolean mStarted;
     private boolean mPaused;
     private final Set<Long> mPendingSeriesRecordings = new ArraySet<>();
-    private final Set<OnSeriesRecordingUpdatedListener> mOnSeriesRecordingUpdatedListeners =
-            new CopyOnWriteArraySet<>();
-
 
     private final SeriesRecordingListener mSeriesRecordingListener = new SeriesRecordingListener() {
         @Override
@@ -107,7 +112,7 @@
         public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
             // Cancel the update.
             for (Iterator<SeriesRecordingUpdateTask> iter = mScheduleTasks.iterator();
-                 iter.hasNext(); ) {
+                    iter.hasNext(); ) {
                 SeriesRecordingUpdateTask task = iter.next();
                 if (CollectionUtils.subtract(task.getSeriesRecordings(), seriesRecordings,
                         SeriesRecording.ID_COMPARATOR).isEmpty()) {
@@ -115,6 +120,13 @@
                     iter.remove();
                 }
             }
+            for (SeriesRecording seriesRecording : seriesRecordings) {
+                FetchSeriesInfoTask task = mFetchSeriesInfoTasks.get(seriesRecording.getId());
+                if (task != null) {
+                    task.cancel(true);
+                    mFetchSeriesInfoTasks.remove(seriesRecording.getId());
+                }
+            }
         }
 
         @Override
@@ -226,7 +238,8 @@
         }
         if (DEBUG) Log.d(TAG, "stop");
         mStarted = false;
-        for (FetchSeriesInfoTask task : mFetchSeriesInfoTasks) {
+        for (int i = 0; i < mFetchSeriesInfoTasks.size(); i++) {
+            FetchSeriesInfoTask task = mFetchSeriesInfoTasks.get(mFetchSeriesInfoTasks.keyAt(i));
             task.cancel(true);
         }
         mFetchSeriesInfoTasks.clear();
@@ -250,7 +263,7 @@
         if (Experiments.CLOUD_EPG.get()) {
             FetchSeriesInfoTask task = new FetchSeriesInfoTask(seriesRecording);
             task.execute();
-            mFetchSeriesInfoTasks.add(task);
+            mFetchSeriesInfoTasks.put(seriesRecording.getId(), task);
         }
     }
 
@@ -363,20 +376,6 @@
         }
     }
 
-    /**
-     * Adds {@link OnSeriesRecordingUpdatedListener}.
-     */
-    public void addOnSeriesRecordingUpdatedListener(OnSeriesRecordingUpdatedListener listener) {
-        mOnSeriesRecordingUpdatedListeners.add(listener);
-    }
-
-    /**
-     * Removes {@link OnSeriesRecordingUpdatedListener}.
-     */
-    public void removeOnSeriesRecordingUpdatedListener(OnSeriesRecordingUpdatedListener listener) {
-        mOnSeriesRecordingUpdatedListeners.remove(listener);
-    }
-
     private boolean needToReadAllChannels(List<SeriesRecording> seriesRecordingsToUpdate) {
         for (SeriesRecording seriesRecording : seriesRecordingsToUpdate) {
             if (seriesRecording.getChannelOption() == SeriesRecording.OPTION_CHANNEL_ALL) {
@@ -403,8 +402,7 @@
     /**
      * @see #pickOneProgramPerEpisode(List, List)
      */
-    @VisibleForTesting
-    static LongSparseArray<List<Program>> pickOneProgramPerEpisode(
+    public static LongSparseArray<List<Program>> pickOneProgramPerEpisode(
             DvrDataManager dataManager, List<SeriesRecording> seriesRecordings,
             List<Program> programs) {
         // Initialize.
@@ -415,7 +413,7 @@
             seriesRecordingIds.put(seriesRecording.getSeriesId(), seriesRecording.getId());
         }
         // Group programs by the episode.
-        Map<ScheduledEpisode, List<Program>> programsForEpisodeMap = new HashMap<>();
+        Map<SeasonEpisodeNumber, List<Program>> programsForEpisodeMap = new HashMap<>();
         for (Program program : programs) {
             long seriesRecordingId = seriesRecordingIds.get(program.getSeriesId());
             if (TextUtils.isEmpty(program.getSeasonNumber())
@@ -424,17 +422,17 @@
                 result.get(seriesRecordingId).add(program);
                 continue;
             }
-            ScheduledEpisode episode = new ScheduledEpisode(seriesRecordingId,
+            SeasonEpisodeNumber seasonEpisodeNumber = new SeasonEpisodeNumber(seriesRecordingId,
                     program.getSeasonNumber(), program.getEpisodeNumber());
-            List<Program> programsForEpisode = programsForEpisodeMap.get(episode);
+            List<Program> programsForEpisode = programsForEpisodeMap.get(seasonEpisodeNumber);
             if (programsForEpisode == null) {
                 programsForEpisode = new ArrayList<>();
-                programsForEpisodeMap.put(episode, programsForEpisode);
+                programsForEpisodeMap.put(seasonEpisodeNumber, programsForEpisode);
             }
             programsForEpisode.add(program);
         }
         // Pick one program.
-        for (Entry<ScheduledEpisode, List<Program>> entry : programsForEpisodeMap.entrySet()) {
+        for (Entry<SeasonEpisodeNumber, List<Program>> entry : programsForEpisodeMap.entrySet()) {
             List<Program> programsForEpisode = entry.getValue();
             Collections.sort(programsForEpisode, new Comparator<Program>() {
                 @Override
@@ -512,13 +510,6 @@
                     mDvrManager.addScheduleToSeriesRecording(seriesRecording, programsToSchedule);
                 }
             }
-            if (!mOnSeriesRecordingUpdatedListeners.isEmpty()) {
-                for (OnSeriesRecordingUpdatedListener listener
-                        : mOnSeriesRecordingUpdatedListeners) {
-                    listener.onSeriesRecordingUpdated(
-                            SeriesRecording.toArray(getSeriesRecordings()));
-                }
-            }
         }
 
         @Override
@@ -543,7 +534,7 @@
 
         @Override
         protected SeriesInfo doInBackground(Void... voids) {
-            return EpgFetcher.createEpgReader(mContext)
+            return EpgFetcher.createEpgReader(mContext, LocationUtils.getCurrentCountry(mContext))
                     .getSeriesInfo(mSeriesRecording.getSeriesId());
         }
 
@@ -561,19 +552,12 @@
                 mFetchedSeriesIds.add(seriesInfo.getId());
                 updateFetchedSeries();
             }
-            mFetchSeriesInfoTasks.remove(this);
+            mFetchSeriesInfoTasks.remove(mSeriesRecording.getId());
         }
 
         @Override
         protected void onCancelled(SeriesInfo seriesInfo) {
-            mFetchSeriesInfoTasks.remove(this);
+            mFetchSeriesInfoTasks.remove(mSeriesRecording.getId());
         }
     }
-
-    /**
-     * A listener to notify when series recording are updated.
-     */
-    public interface OnSeriesRecordingUpdatedListener {
-        void onSeriesRecordingUpdated(SeriesRecording... seriesRecordings);
-    }
 }
diff --git a/src/com/android/tv/dvr/ui/BigArguments.java b/src/com/android/tv/dvr/ui/BigArguments.java
new file mode 100644
index 0000000..ec3b506
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/BigArguments.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui;
+
+import android.support.annotation.NonNull;
+
+import com.android.tv.common.SoftPreconditions;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Stores the object to pass through activities/fragments.
+ */
+public class BigArguments {
+    private final static String TAG = "BigArguments";
+    private static Map<String, Object> sBigArgumentMap = new HashMap<>();
+
+    /**
+     * Sets the argument.
+     */
+    public static void setArgument(String name, @NonNull Object value) {
+        SoftPreconditions.checkState(value != null, TAG, "Set argument, but value is null");
+        sBigArgumentMap.put(name, value);
+    }
+
+    /**
+     * Returns the argument which is associated to the name.
+     */
+    public static Object getArgument(String name) {
+        return sBigArgumentMap.get(name);
+    }
+
+    /**
+     * Resets the arguments.
+     */
+    public static void reset() {
+        sBigArgumentMap.clear();
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/ChangeImageTransformWithScaledParent.java b/src/com/android/tv/dvr/ui/ChangeImageTransformWithScaledParent.java
new file mode 100644
index 0000000..cddece7
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/ChangeImageTransformWithScaledParent.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Matrix;
+import android.graphics.drawable.BitmapDrawable;
+import android.transition.ChangeImageTransform;
+import android.transition.TransitionValues;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.ImageView.ScaleType;
+
+import com.android.tv.R;
+
+import java.util.Map;
+
+/**
+ * TODO: Remove this class once b/32405620 is fixed.
+ * This class is for the workaround of b/32405620 and only for the shared element transition between
+ * {@link com.android.tv.dvr.ui.browse.RecordingCardView} and
+ * {@link com.android.tv.dvr.ui.browse.DvrDetailsActivity}.
+ */
+public class ChangeImageTransformWithScaledParent extends ChangeImageTransform {
+    private static final String PROPNAME_MATRIX = "android:changeImageTransform:matrix";
+
+    public ChangeImageTransformWithScaledParent(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        super.captureStartValues(transitionValues);
+        applyParentScale(transitionValues);
+    }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) {
+        super.captureEndValues(transitionValues);
+        applyParentScale(transitionValues);
+    }
+
+    private void applyParentScale(TransitionValues transitionValues) {
+        View view = transitionValues.view;
+        Map<String, Object> values = transitionValues.values;
+        Matrix matrix = (Matrix) values.get(PROPNAME_MATRIX);
+        if (matrix != null && view.getId() == R.id.details_overview_image
+                && view instanceof ImageView) {
+            ImageView imageView = (ImageView) view;
+            if (imageView.getScaleType() == ScaleType.CENTER_INSIDE
+                    && imageView.getDrawable() instanceof BitmapDrawable) {
+                Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
+                if (bitmap.getWidth() < imageView.getWidth()
+                        && bitmap.getHeight() < imageView.getHeight()) {
+                    float scale = imageView.getContext().getResources().getFraction(
+                            R.fraction.lb_focus_zoom_factor_medium, 1, 1);
+                    matrix.postScale(scale, scale, imageView.getWidth() / 2,
+                            imageView.getHeight() / 2);
+                }
+            }
+        }
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/CurrentRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/CurrentRecordingDetailsFragment.java
deleted file mode 100644
index 5d8e20f..0000000
--- a/src/com/android/tv/dvr/ui/CurrentRecordingDetailsFragment.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.content.res.Resources;
-import android.support.v17.leanback.widget.Action;
-import android.support.v17.leanback.widget.OnActionClickedListener;
-import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
-
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.dvr.DvrManager;
-
-/**
- * {@link RecordingDetailsFragment} for current recording in DVR.
- */
-public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
-    private static final int ACTION_STOP_RECORDING = 1;
-
-    @Override
-    protected SparseArrayObjectAdapter onCreateActionsAdapter() {
-        SparseArrayObjectAdapter adapter =
-                new SparseArrayObjectAdapter(new ActionPresenterSelector());
-        Resources res = getResources();
-        adapter.set(ACTION_STOP_RECORDING, new Action(ACTION_STOP_RECORDING,
-                res.getString(R.string.epg_dvr_dialog_message_stop_recording), null,
-                res.getDrawable(R.drawable.lb_ic_stop)));
-        return adapter;
-    }
-
-    @Override
-    protected OnActionClickedListener onCreateOnActionClickedListener() {
-        return new OnActionClickedListener() {
-            @Override
-            public void onActionClicked(Action action) {
-                if (action.getId() == ACTION_STOP_RECORDING) {
-                    DvrManager dvrManager = TvApplication.getSingletons(getActivity())
-                            .getDvrManager();
-                    dvrManager.stopRecording(getRecording());
-                }
-                getActivity().finish();
-            }
-        };
-    }
-}
diff --git a/src/com/android/tv/dvr/ui/DetailsContent.java b/src/com/android/tv/dvr/ui/DetailsContent.java
deleted file mode 100644
index 19521fc..0000000
--- a/src/com/android/tv/dvr/ui/DetailsContent.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.media.tv.TvContract;
-import android.support.annotation.Nullable;
-import android.text.TextUtils;
-
-import com.android.tv.data.BaseProgram;
-import com.android.tv.data.Channel;
-
-/**
- * A class for details content.
- */
-public class DetailsContent {
-    /** Constant for invalid time. */
-    public static final long INVALID_TIME = -1;
-
-    private CharSequence mTitle;
-    private long mStartTimeUtcMillis;
-    private long mEndTimeUtcMillis;
-    private String mDescription;
-    private String mLogoImageUri;
-    private String mBackgroundImageUri;
-
-    private DetailsContent() { }
-
-    /**
-     * Returns title.
-     */
-    public CharSequence getTitle() {
-        return mTitle;
-    }
-
-    /**
-     * Returns start time.
-     */
-    public long getStartTimeUtcMillis() {
-        return mStartTimeUtcMillis;
-    }
-
-    /**
-     * Returns end time.
-     */
-    public long getEndTimeUtcMillis() {
-        return mEndTimeUtcMillis;
-    }
-
-    /**
-     * Returns description.
-     */
-    public String getDescription() {
-        return mDescription;
-    }
-
-    /**
-     * Returns Logo image URI as a String.
-     */
-    public String getLogoImageUri() {
-        return mLogoImageUri;
-    }
-
-    /**
-     * Returns background image URI as a String.
-     */
-    public String getBackgroundImageUri() {
-        return mBackgroundImageUri;
-    }
-
-    /**
-     * Copies other details content.
-     */
-    public void copyFrom(DetailsContent other) {
-        if (this == other) {
-            return;
-        }
-        mTitle = other.mTitle;
-        mStartTimeUtcMillis = other.mStartTimeUtcMillis;
-        mEndTimeUtcMillis = other.mEndTimeUtcMillis;
-        mDescription = other.mDescription;
-        mLogoImageUri = other.mLogoImageUri;
-        mBackgroundImageUri = other.mBackgroundImageUri;
-    }
-
-    /**
-     * A class for building details content.
-     */
-    public static final class Builder {
-        private final DetailsContent mDetailsContent;
-
-        public Builder() {
-            mDetailsContent = new DetailsContent();
-            mDetailsContent.mStartTimeUtcMillis = INVALID_TIME;
-            mDetailsContent.mEndTimeUtcMillis = INVALID_TIME;
-        }
-
-        /**
-         * Sets title.
-         */
-        public Builder setTitle(CharSequence title) {
-            mDetailsContent.mTitle = title;
-            return this;
-        }
-
-        /**
-         * Sets start time.
-         */
-        public Builder setStartTimeUtcMillis(long startTimeUtcMillis) {
-            mDetailsContent.mStartTimeUtcMillis = startTimeUtcMillis;
-            return this;
-        }
-
-        /**
-         * Sets end time.
-         */
-        public Builder setEndTimeUtcMillis(long endTimeUtcMillis) {
-            mDetailsContent.mEndTimeUtcMillis = endTimeUtcMillis;
-            return this;
-        }
-
-        /**
-         * Sets description.
-         */
-        public Builder setDescription(String description) {
-            mDetailsContent.mDescription = description;
-            return this;
-        }
-
-        /**
-         * Sets logo image URI as a String.
-         */
-        public Builder setLogoImageUri(String logoImageUri) {
-            mDetailsContent.mLogoImageUri = logoImageUri;
-            return this;
-        }
-
-        /**
-         * Sets background image URI as a String.
-         */
-        public Builder setBackgroundImageUri(String backgroundImageUri) {
-            mDetailsContent.mBackgroundImageUri = backgroundImageUri;
-            return this;
-        }
-
-        /**
-         * Sets background image and logo image URI from program and channel.
-         */
-        public Builder setImageUris(@Nullable BaseProgram program, @Nullable Channel channel) {
-            if (program != null) {
-                return setImageUris(program.getPosterArtUri(), program.getThumbnailUri(), channel);
-            } else {
-                return setImageUris(null, null, channel);
-            }
-        }
-
-        /**
-         * Sets background image and logo image URI and channel is used for fallback images.
-         */
-        public Builder setImageUris(@Nullable String posterArtUri,
-                @Nullable String thumbnailUri, @Nullable Channel channel) {
-            mDetailsContent.mLogoImageUri = null;
-            mDetailsContent.mBackgroundImageUri = null;
-            if (!TextUtils.isEmpty(posterArtUri) && !TextUtils.isEmpty(thumbnailUri)) {
-                mDetailsContent.mLogoImageUri = posterArtUri;
-                mDetailsContent.mBackgroundImageUri = thumbnailUri;
-            } else if (!TextUtils.isEmpty(posterArtUri)) {
-                // thumbnailUri is empty
-                mDetailsContent.mLogoImageUri = posterArtUri;
-                mDetailsContent.mBackgroundImageUri = posterArtUri;
-            } else if (!TextUtils.isEmpty(thumbnailUri)) {
-                // posterArtUri is empty
-                mDetailsContent.mLogoImageUri = thumbnailUri;
-                mDetailsContent.mBackgroundImageUri = thumbnailUri;
-            }
-            if (TextUtils.isEmpty(mDetailsContent.mLogoImageUri) && channel != null) {
-                String channelLogoUri = TvContract.buildChannelLogoUri(channel.getId())
-                        .toString();
-                mDetailsContent.mLogoImageUri = channelLogoUri;
-                mDetailsContent.mBackgroundImageUri = channelLogoUri;
-            }
-            return this;
-        }
-
-        /**
-         * Builds details content.
-         */
-        public DetailsContent build() {
-            DetailsContent detailsContent = new DetailsContent();
-            detailsContent.copyFrom(mDetailsContent);
-            return detailsContent;
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java b/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
index 9df228d..6232787 100644
--- a/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrAlreadyRecordedFragment.java
@@ -24,15 +24,12 @@
 import android.support.annotation.NonNull;
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
 import android.support.v17.leanback.widget.GuidedAction;
-import android.widget.Toast;
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.dvr.RecordedProgram;
 import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.util.Utils;
+import com.android.tv.dvr.data.RecordedProgram;
 
 import java.util.List;
 
@@ -92,7 +89,7 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         if (action.getId() == ACTION_RECORD_ANYWAY) {
             getDvrManager().addSchedule(mProgram);
         } else if (action.getId() == ACTION_WATCH) {
@@ -100,4 +97,23 @@
         }
         dismissDialog();
     }
+
+    @Override
+    public String getTrackerPrefix() {
+        return "onTrackedGuidedActionClicked";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_RECORD_ANYWAY) {
+            return "record-anyway";
+        } else if (actionId == ACTION_WATCH) {
+            return "watch-now";
+        } else if (actionId == ACTION_CANCEL) {
+            return "cancel-recording";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
 }
diff --git a/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java b/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
index 78f2178..6da75e5 100644
--- a/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrAlreadyScheduledFragment.java
@@ -25,15 +25,12 @@
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
 import android.support.v17.leanback.widget.GuidedAction;
 import android.text.format.DateUtils;
-import android.widget.Toast;
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
 import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.util.Utils;
+import com.android.tv.dvr.data.ScheduledRecording;
 
 import java.util.List;
 
@@ -95,7 +92,7 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         if (action.getId() == ACTION_RECORD_ANYWAY) {
             getDvrManager().addSchedule(mProgram);
         } else if (action.getId() == ACTION_RECORD_INSTEAD) {
@@ -104,4 +101,23 @@
         }
         dismissDialog();
     }
+
+    @Override
+    public String getTrackerPrefix() {
+        return "DvrAlreadyScheduledFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_RECORD_ANYWAY) {
+            return "record-anyway";
+        } else if (actionId == ACTION_RECORD_INSTEAD) {
+            return "record-instead";
+        } else if (actionId == ACTION_CANCEL) {
+            return "cancel-recording";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
 }
diff --git a/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java b/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
index 837d8ab..3665941 100644
--- a/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrChannelRecordDurationOptionFragment.java
@@ -27,7 +27,7 @@
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.ui.DvrConflictFragment.DvrChannelRecordConflictFragment;
 
 import java.util.ArrayList;
@@ -85,7 +85,7 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
         long duration = mDurations.get((int) action.getId());
         long startTimeMs = System.currentTimeMillis();
@@ -106,4 +106,25 @@
                     R.id.halfsized_dialog_host);
         }
     }
+
+    @Override
+    public String getTrackerPrefix() {
+        return "DvrChannelRecordDurationOptionFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == 0) {
+            return "record-10-minutes";
+        } else if (actionId == 1) {
+            return "record-30-minutes";
+        } else if (actionId == 2) {
+            return "record-1-hour";
+        } else if (actionId == 3) {
+            return "record-3-hour";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
 }
diff --git a/src/com/android/tv/dvr/ui/DvrConflictFragment.java b/src/com/android/tv/dvr/ui/DvrConflictFragment.java
index e7be4d0..6f362e6 100644
--- a/src/com/android/tv/dvr/ui/DvrConflictFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrConflictFragment.java
@@ -34,10 +34,9 @@
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.data.Program;
-import com.android.tv.dvr.ConflictChecker;
-import com.android.tv.dvr.ConflictChecker.OnUpcomingConflictChangeListener;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.recorder.ConflictChecker;
+import com.android.tv.dvr.recorder.ConflictChecker.OnUpcomingConflictChangeListener;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.util.Utils;
 
 import java.util.ArrayList;
@@ -85,7 +84,7 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         if (action.getId() == ACTION_VIEW_SCHEDULES) {
             DvrUiHelper.startSchedulesActivityForOneTimeRecordingConflict(
                     getContext(), getConflicts());
@@ -93,6 +92,16 @@
         dismissDialog();
     }
 
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = getId();
+        if (actionId == ACTION_VIEW_SCHEDULES) {
+            return "view-schedules";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
+
     String getConflictDescription() {
         List<String> titles = new ArrayList<>();
         HashSet<String> titleSet = new HashSet<>();
@@ -185,6 +194,11 @@
             Drawable icon = getResources().getDrawable(R.drawable.ic_error_white_48dp, null);
             return new Guidance(title, descriptionPrefix + " " + description, null, icon);
         }
+
+        @Override
+        public String getTrackerPrefix() {
+            return "DvrProgramConflictFragment";
+        }
     }
 
     /**
@@ -236,6 +250,11 @@
             Drawable icon = getResources().getDrawable(R.drawable.ic_error_white_48dp, null);
             return new Guidance(title, descriptionPrefix + " " + description, null, icon);
         }
+
+        @Override
+        public String getTrackerPrefix() {
+            return "DvrChannelRecordConflictFragment";
+        }
     }
 
     /**
@@ -300,7 +319,7 @@
         }
 
         @Override
-        public void onGuidedActionClicked(GuidedAction action) {
+        public void onTrackedGuidedActionClicked(GuidedAction action) {
             if (action.getId() == ACTION_CANCEL) {
                 ConflictChecker checker = ((MainActivity) getContext()).getDvrConflictChecker();
                 if (checker != null) {
@@ -319,6 +338,23 @@
         }
 
         @Override
+        public String getTrackerPrefix() {
+            return "DvrChannelWatchConflictFragment";
+        }
+
+        @Override
+        public String getTrackerLabelForGuidedAction(GuidedAction action) {
+            long actionId = action.getId();
+            if (actionId == ACTION_CANCEL) {
+                return "cancel";
+            } else if (actionId == ACTION_DELETE_CONFLICT) {
+                return "delete";
+            } else {
+                return super.getTrackerLabelForGuidedAction(action);
+            }
+        }
+
+        @Override
         public void onDetach() {
             ConflictChecker checker = ((MainActivity) getContext()).getDvrConflictChecker();
             if (checker != null) {
diff --git a/src/com/android/tv/dvr/ui/DvrForgetStorageErrorFragment.java b/src/com/android/tv/dvr/ui/DvrForgetStorageErrorFragment.java
deleted file mode 100644
index 73ddcdd..0000000
--- a/src/com/android/tv/dvr/ui/DvrForgetStorageErrorFragment.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
-import android.support.v17.leanback.widget.GuidedAction;
-import android.text.TextUtils;
-
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.common.SoftPreconditions;
-import com.android.tv.dvr.DvrDataManager;
-import com.android.tv.dvr.DvrManager;
-
-import java.util.List;
-
-public class DvrForgetStorageErrorFragment extends DvrGuidedStepFragment {
-    private static final int ACTION_CANCEL = 1;
-    private static final int ACTION_FORGET_STORAGE = 2;
-    private String mInputId;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        Bundle args = getArguments();
-        if (args != null) {
-            mInputId = args.getString(DvrHalfSizedDialogFragment.KEY_INPUT_ID);
-        }
-        SoftPreconditions.checkArgument(!TextUtils.isEmpty(mInputId));
-        super.onCreate(savedInstanceState);
-    }
-
-    @NonNull
-    @Override
-    public Guidance onCreateGuidance(Bundle savedInstanceState) {
-        String title = getResources().getString(R.string.dvr_error_forget_storage_title);
-        String description = getResources().getString(
-                R.string.dvr_error_forget_storage_description);
-        return new Guidance(title, description, null, null);
-    }
-
-    @Override
-    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
-        Activity activity = getActivity();
-        actions.add(new GuidedAction.Builder(activity)
-                .id(ACTION_CANCEL)
-                .title(getResources().getString(R.string.dvr_action_error_cancel))
-                .build());
-        actions.add(new GuidedAction.Builder(activity)
-                .id(ACTION_FORGET_STORAGE)
-                .title(getResources().getString(R.string.dvr_action_error_forget_storage))
-                .build());
-    }
-
-    @Override
-    public void onGuidedActionClicked(GuidedAction action) {
-        if (action.getId() != ACTION_FORGET_STORAGE) {
-            dismissDialog();
-            return;
-        }
-        DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
-        dvrManager.forgetStorage(mInputId);
-        Activity activity = getActivity();
-        if (activity instanceof DvrDetailsActivity) {
-            // Since we removed everything, just finish the activity.
-            activity.finish();
-        } else {
-            dismissDialog();
-        }
-    }
-}
diff --git a/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java b/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
index d26e683..ab852e1 100644
--- a/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrGuidedStepFragment.java
@@ -16,24 +16,43 @@
 
 package com.android.tv.dvr.ui;
 
+import android.app.Activity;
 import android.app.DialogFragment;
 import android.content.Context;
 import android.os.Bundle;
-import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidanceStylist;
 import android.support.v17.leanback.widget.GuidedAction;
 import android.support.v17.leanback.widget.VerticalGridView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.tv.ApplicationSingletons;
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.TvApplication;
+import com.android.tv.dialog.HalfSizedDialogFragment.OnActionClickListener;
 import com.android.tv.dialog.SafeDismissDialogFragment;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ui.HalfSizedDialogFragment.OnActionClickListener;
+import com.android.tv.dvr.DvrStorageStatusManager;
 
-public class DvrGuidedStepFragment extends GuidedStepFragment {
+import java.util.List;
+
+public abstract class DvrGuidedStepFragment extends TrackedGuidedStepFragment {
+    /**
+     * Action ID for "recording/scheduling the program anyway".
+     */
+    public static final int ACTION_RECORD_ANYWAY = 1;
+    /**
+     * Action ID for "deleting existed recordings".
+     */
+    public static final int ACTION_DELETE_RECORDINGS = 2;
+    /**
+     * Action ID for "cancelling current recording request".
+     */
+    public static final int ACTION_CANCEL_RECORDING = 3;
+    public static final String UNKNOWN_DVR_ACTION = "Unknown DVR Action";
+
     private DvrManager mDvrManager;
     private OnActionClickListener mOnActionClickListener;
 
@@ -44,7 +63,8 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-        mDvrManager = TvApplication.getSingletons(context).getDvrManager();
+        ApplicationSingletons singletons = TvApplication.getSingletons(context);
+        mDvrManager = singletons.getDvrManager();
     }
 
     @Override
@@ -64,13 +84,27 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         if (mOnActionClickListener != null) {
             mOnActionClickListener.onActionClick(action.getId());
         }
         dismissDialog();
     }
 
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_RECORD_ANYWAY) {
+            return "record-anyway";
+        } else if (actionId == ACTION_DELETE_RECORDINGS) {
+            return "delete-recordings";
+        } else if (actionId == ACTION_CANCEL_RECORDING) {
+            return "cancel-recording";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
+
     protected void dismissDialog() {
         if (getActivity() instanceof MainActivity) {
             SafeDismissDialogFragment currentDialog =
@@ -86,4 +120,76 @@
     protected void setOnActionClickListener(OnActionClickListener listener) {
         mOnActionClickListener = listener;
     }
+
+    /**
+     * The inner guided step fragment for
+     * {@link com.android.tv.dvr.ui.DvrHalfSizedDialogFragment
+     * .DvrNoFreeSpaceErrorDialogFragment}.
+     */
+    public static class DvrNoFreeSpaceErrorFragment extends DvrGuidedStepFragment {
+        @Override
+        public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
+            return new GuidanceStylist.Guidance(getString(R.string.dvr_error_no_free_space_title),
+                    getString(R.string.dvr_error_no_free_space_description), null, null);
+        }
+
+        @Override
+        public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
+            Activity activity = getActivity();
+            actions.add(new GuidedAction.Builder(activity)
+                    .id(ACTION_RECORD_ANYWAY)
+                    .title(R.string.dvr_action_record_anyway)
+                    .build());
+            actions.add(new GuidedAction.Builder(activity)
+                    .id(ACTION_DELETE_RECORDINGS)
+                    .title(R.string.dvr_action_delete_recordings)
+                    .build());
+            actions.add(new GuidedAction.Builder(activity)
+                    .id(ACTION_CANCEL_RECORDING)
+                    .title(R.string.dvr_action_record_cancel)
+                    .build());
+        }
+
+        @Override
+        public String getTrackerPrefix() {
+            return "DvrNoFreeSpaceErrorFragment";
+        }
+    }
+
+    /**
+     * The inner guided step fragment for
+     * {@link com.android.tv.dvr.ui.DvrHalfSizedDialogFragment
+     * .DvrSmallSizedStorageErrorDialogFragment}.
+     */
+    public static class DvrSmallSizedStorageErrorFragment extends DvrGuidedStepFragment {
+        @Override
+        public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) {
+            String title = getResources().getString(
+                    R.string.dvr_error_small_sized_storage_title);
+            String description = getResources().getString(
+                    R.string.dvr_error_small_sized_storage_description,
+                    DvrStorageStatusManager.MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES / 1024
+                            / 1024 / 1024);
+            return new GuidanceStylist.Guidance(title, description, null, null);
+        }
+
+        @Override
+        public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
+            Activity activity = getActivity();
+            actions.add(new GuidedAction.Builder(activity)
+                    .id(GuidedAction.ACTION_ID_OK)
+                    .title(android.R.string.ok)
+                    .build());
+        }
+
+        @Override
+        public void onTrackedGuidedActionClicked(GuidedAction action) {
+            dismissDialog();
+        }
+
+        @Override
+        public String getTrackerPrefix() {
+            return "DvrSmallSizedStorageErrorFragment";
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java b/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
index 2b132db..f8ef385 100644
--- a/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrHalfSizedDialogFragment.java
@@ -29,6 +29,7 @@
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.dvr.DvrStorageStatusManager;
+import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dvr.ui.DvrConflictFragment.DvrChannelWatchConflictFragment;
 import com.android.tv.dvr.ui.DvrConflictFragment.DvrProgramConflictFragment;
 import com.android.tv.guide.ProgramGuide;
@@ -166,6 +167,17 @@
     }
 
     /**
+     * A dialog fragment to show error message when there is no enough free space to record.
+     */
+    public static class DvrNoFreeSpaceErrorDialogFragment
+            extends DvrGuidedStepDialogFragment {
+        @Override
+        protected DvrGuidedStepFragment onCreateGuidedStepFragment() {
+            return new DvrGuidedStepFragment.DvrNoFreeSpaceErrorFragment();
+        }
+    }
+
+    /**
      * A dialog fragment to show error message when the current storage is too small to
      * support DVR
      */
@@ -173,32 +185,7 @@
             extends DvrGuidedStepDialogFragment {
         @Override
         protected DvrGuidedStepFragment onCreateGuidedStepFragment() {
-            return new DvrGuidedStepFragment() {
-                @Override
-                public Guidance onCreateGuidance(Bundle savedInstanceState) {
-                    String title = getResources().getString(
-                            R.string.dvr_error_small_sized_storage_title);
-                    String description = getResources().getString(
-                            R.string.dvr_error_small_sized_storage_description,
-                            DvrStorageStatusManager.MIN_STORAGE_SIZE_FOR_DVR_IN_BYTES / 1024
-                                    / 1024 / 1024);
-                    return new Guidance(title, description, null, null);
-                }
-
-                @Override
-                public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
-                    Activity activity = getActivity();
-                    actions.add(new GuidedAction.Builder(activity)
-                            .id(GuidedAction.ACTION_ID_OK)
-                            .title(android.R.string.ok)
-                            .build());
-                }
-
-                @Override
-                public void onGuidedActionClicked(GuidedAction action) {
-                    dismissDialog();
-                }
-            };
+            return new DvrGuidedStepFragment.DvrSmallSizedStorageErrorFragment();
         }
     }
 
diff --git a/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java b/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
index 3b1dbfa..182416b 100644
--- a/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrInsufficientSpaceErrorFragment.java
@@ -17,6 +17,7 @@
 package com.android.tv.dvr.ui;
 
 import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
@@ -24,19 +25,67 @@
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.common.SoftPreconditions;
+import com.android.tv.dvr.ui.browse.DvrBrowseActivity;
 
+import java.util.ArrayList;
 import java.util.List;
 
 public class DvrInsufficientSpaceErrorFragment extends DvrGuidedStepFragment {
-    private static final int ACTION_DONE = 1;
-    private static final int ACTION_OPEN_DVR = 2;
+    /**
+     * Key for the failed scheduled recordings information.
+     */
+    public static final String FAILED_SCHEDULED_RECORDING_INFOS =
+            "failed_scheduled_recording_infos";
+
+    private static final String TAG = "DvrInsufficientSpaceErrorFragment";
+
+    private static final int ACTION_VIEW_RECENT_RECORDINGS = 1;
+
+    private ArrayList<String> mFailedScheduledRecordingInfos;
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        Bundle args = getArguments();
+        if (args != null) {
+            mFailedScheduledRecordingInfos =
+                    args.getStringArrayList(FAILED_SCHEDULED_RECORDING_INFOS);
+        }
+        SoftPreconditions.checkState(
+                mFailedScheduledRecordingInfos != null && !mFailedScheduledRecordingInfos.isEmpty(),
+                TAG, "failed scheduled recording is null");
+    }
 
     @Override
     public Guidance onCreateGuidance(Bundle savedInstanceState) {
-        String title = getResources().getString(R.string.dvr_error_insufficient_space_title);
-        String description = getResources()
-                .getString(R.string.dvr_error_insufficient_space_description);
+        String title;
+        String description;
+        int failedScheduledRecordingSize = mFailedScheduledRecordingInfos.size();
+        if (failedScheduledRecordingSize == 1) {
+            title =  getString(
+                    R.string.dvr_error_insufficient_space_title_one_recording,
+                    mFailedScheduledRecordingInfos.get(0));
+            description = getString(
+                    R.string.dvr_error_insufficient_space_description_one_recording,
+                    mFailedScheduledRecordingInfos.get(0));
+        } else if (failedScheduledRecordingSize == 2) {
+            title =  getString(
+                    R.string.dvr_error_insufficient_space_title_two_recordings,
+                    mFailedScheduledRecordingInfos.get(0), mFailedScheduledRecordingInfos.get(1));
+            description = getString(
+                    R.string.dvr_error_insufficient_space_description_two_recordings,
+                    mFailedScheduledRecordingInfos.get(0), mFailedScheduledRecordingInfos.get(1));
+        } else {
+            title =  getString(
+                    R.string.dvr_error_insufficient_space_title_three_or_more_recordings,
+                    mFailedScheduledRecordingInfos.get(0), mFailedScheduledRecordingInfos.get(1),
+                    mFailedScheduledRecordingInfos.get(2));
+            description = getString(
+                    R.string.dvr_error_insufficient_space_description_three_or_more_recordings,
+                    mFailedScheduledRecordingInfos.get(0), mFailedScheduledRecordingInfos.get(1),
+                    mFailedScheduledRecordingInfos.get(2));
+        }
         return new Guidance(title, description, null, null);
     }
 
@@ -44,28 +93,38 @@
     public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
         Activity activity = getActivity();
         actions.add(new GuidedAction.Builder(activity)
-                .id(ACTION_DONE)
-                .title(getResources().getString(R.string.dvr_action_error_done))
+                .clickAction(GuidedAction.ACTION_ID_OK)
                 .build());
-        DvrDataManager dvrDataManager = TvApplication.getSingletons(getContext())
-                .getDvrDataManager();
-        if (!(dvrDataManager.getRecordedPrograms().isEmpty()
-                && dvrDataManager.getStartedRecordings().isEmpty()
-                && dvrDataManager.getNonStartedScheduledRecordings().isEmpty()
-                && dvrDataManager.getSeriesRecordings().isEmpty())) {
-                    actions.add(new GuidedAction.Builder(activity)
-                            .id(ACTION_OPEN_DVR)
-                            .title(getResources().getString(R.string.dvr_action_error_open_dvr))
-                            .build());
+        if (TvApplication.getSingletons(getContext()).getDvrManager().hasValidItems()) {
+            actions.add(new GuidedAction.Builder(activity)
+                    .id(ACTION_VIEW_RECENT_RECORDINGS)
+                    .title(getResources().getString(
+                            R.string.dvr_error_insufficient_space_action_view_recent_recordings))
+                    .build());
         }
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
-        if (action.getId() == ACTION_OPEN_DVR) {
-            Intent intent = new Intent(getActivity(), DvrActivity.class);
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
+        if (action.getId() == ACTION_VIEW_RECENT_RECORDINGS) {
+            Intent intent = new Intent(getActivity(), DvrBrowseActivity.class);
             getActivity().startActivity(intent);
         }
         dismissDialog();
     }
+
+    @Override
+    public String getTrackerPrefix() {
+        return "DvrInsufficientSpaceErrorFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_VIEW_RECENT_RECORDINGS) {
+            return "view-recent";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
 }
diff --git a/src/com/android/tv/dvr/ui/DvrItemPresenter.java b/src/com/android/tv/dvr/ui/DvrItemPresenter.java
deleted file mode 100644
index 339e5d2..0000000
--- a/src/com/android/tv/dvr/ui/DvrItemPresenter.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.app.Activity;
-import android.support.annotation.CallSuper;
-import android.support.v17.leanback.widget.Presenter;
-import android.view.View;
-import android.view.View.OnClickListener;
-
-import com.android.tv.dvr.DvrUiHelper;
-
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-/**
- * An abstract class to present DVR items in {@link RecordingCardView}, which is mainly used in
- * {@link DvrBrowseFragment}. DVR items might include: {@link ScheduledRecording},
- * {@link RecordedProgram}, and {@link SeriesRecording}.
- */
-public abstract class DvrItemPresenter extends Presenter {
-    private final Set<ViewHolder> mBoundViewHolders = new HashSet<>();
-    private final OnClickListener mOnClickListener = onCreateOnClickListener();
-
-    @Override
-    @CallSuper
-    public void onBindViewHolder(ViewHolder viewHolder, Object o) {
-        viewHolder.view.setTag(o);
-        viewHolder.view.setOnClickListener(mOnClickListener);
-        mBoundViewHolders.add(viewHolder);
-    }
-
-    @Override
-    @CallSuper
-    public void onUnbindViewHolder(ViewHolder viewHolder) {
-        mBoundViewHolders.remove(viewHolder);
-    }
-
-    /**
-     * Unbinds all bound view holders.
-     */
-    public void unbindAllViewHolders() {
-        // When browse fragments are destroyed, RecyclerView would not call presenters'
-        // onUnbindViewHolder(). We should handle it by ourselves to prevent resources leaks.
-        for (ViewHolder viewHolder : new HashSet<>(mBoundViewHolders)) {
-            onUnbindViewHolder(viewHolder);
-        }
-    }
-
-    /**
-     * Creates {@link OnClickListener} for DVR library's card views.
-     */
-    protected OnClickListener onCreateOnClickListener() {
-        return new OnClickListener() {
-            @Override
-            public void onClick(View view) {
-                if (view instanceof RecordingCardView) {
-                    RecordingCardView v = (RecordingCardView) view;
-                    DvrUiHelper.startDetailsActivity((Activity) v.getContext(),
-                            v.getTag(), v.getImageView(), false);
-                }
-            }
-        };
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java b/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
index 2e2c284..e726995 100644
--- a/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrMissingStorageErrorFragment.java
@@ -17,29 +17,27 @@
 package com.android.tv.dvr.ui;
 
 import android.app.Activity;
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
 import android.os.Bundle;
-import android.support.v17.leanback.app.GuidedStepFragment;
+import android.provider.Settings;
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
 import android.support.v17.leanback.widget.GuidedAction;
-import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.tv.R;
-import com.android.tv.common.SoftPreconditions;
+import com.android.tv.dvr.ui.browse.DvrDetailsActivity;
 
 import java.util.List;
 
 public class DvrMissingStorageErrorFragment extends DvrGuidedStepFragment {
-    private static final int ACTION_CANCEL = 1;
-    private static final int ACTION_FORGET_STORAGE = 2;
-    private String mInputId;
+    private static final String TAG = "DvrMissingStorageError";
+
+    private static final int ACTION_OK = 1;
+    private static final int ACTION_OPEN_STORAGE_SETTINGS = 2;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        Bundle args = getArguments();
-        if (args != null) {
-            mInputId = args.getString(DvrHalfSizedDialogFragment.KEY_INPUT_ID);
-        }
-        SoftPreconditions.checkArgument(!TextUtils.isEmpty(mInputId));
         super.onCreate(savedInstanceState);
     }
 
@@ -55,25 +53,46 @@
     public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
         Activity activity = getActivity();
         actions.add(new GuidedAction.Builder(activity)
-                .id(ACTION_CANCEL)
-                .title(getResources().getString(R.string.dvr_action_error_cancel))
+                .id(ACTION_OK)
+                .title(android.R.string.ok)
                 .build());
         actions.add(new GuidedAction.Builder(activity)
-                .id(ACTION_FORGET_STORAGE)
-                .title(getResources().getString(R.string.dvr_action_error_forget_storage))
+                .id(ACTION_OPEN_STORAGE_SETTINGS)
+                .title(getResources().getString(R.string.dvr_action_error_storage_settings))
                 .build());
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
-        if (action.getId() == ACTION_FORGET_STORAGE) {
-            DvrForgetStorageErrorFragment fragment = new DvrForgetStorageErrorFragment();
-            Bundle args = new Bundle();
-            args.putString(DvrHalfSizedDialogFragment.KEY_INPUT_ID, mInputId);
-            fragment.setArguments(args);
-            GuidedStepFragment.add(getFragmentManager(), fragment, R.id.halfsized_dialog_host);
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
+        Activity activity = getActivity();
+        if (activity instanceof DvrDetailsActivity) {
+            activity.finish();
+        } else {
+            dismissDialog();
+        }
+        if (action.getId() != ACTION_OPEN_STORAGE_SETTINGS) {
             return;
         }
-        dismissDialog();
+        final Intent intent = new Intent(Settings.ACTION_INTERNAL_STORAGE_SETTINGS);
+        try {
+            getContext().startActivity(intent);
+        } catch (ActivityNotFoundException e) {
+            Log.e(TAG, "Can't start internal storage settings activity", e);
+        }
     }
-}
\ No newline at end of file
+
+    @Override
+    public String getTrackerPrefix() {
+        return "DvrMissingStorageErrorFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_OPEN_STORAGE_SETTINGS) {
+            return "open-storage-settings";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/DvrPlaybackCardPresenter.java b/src/com/android/tv/dvr/ui/DvrPlaybackCardPresenter.java
deleted file mode 100644
index 8c4c856..0000000
--- a/src/com/android/tv/dvr/ui/DvrPlaybackCardPresenter.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2016 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.dvr.ui;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.Resources;
-import android.text.TextUtils;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-
-import com.android.tv.R;
-import com.android.tv.dvr.RecordedProgram;
-import com.android.tv.dvr.DvrPlaybackActivity;
-import com.android.tv.util.Utils;
-
-/**
- * This class is used to generate Views and bind Objects for related recordings in DVR playback.
- */
-public class DvrPlaybackCardPresenter extends RecordedProgramPresenter {
-    private static final String TAG = "DvrPlaybackCardPresenter";
-    private static final boolean DEBUG = false;
-
-    private final int mRelatedRecordingCardWidth;
-    private final int mRelatedRecordingCardHeight;
-
-    DvrPlaybackCardPresenter(Context context) {
-        super(context);
-        mRelatedRecordingCardWidth =
-                context.getResources().getDimensionPixelSize(R.dimen.dvr_related_recordings_width);
-        mRelatedRecordingCardHeight =
-                context.getResources().getDimensionPixelSize(R.dimen.dvr_related_recordings_height);
-    }
-
-    @Override
-    public ViewHolder onCreateViewHolder(ViewGroup parent) {
-        Resources res = parent.getResources();
-        RecordingCardView view = new RecordingCardView(
-                getContext(), mRelatedRecordingCardWidth, mRelatedRecordingCardHeight);
-        return new ViewHolder(view);
-    }
-
-    @Override
-    protected OnClickListener onCreateOnClickListener() {
-        return new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                long programId = ((RecordedProgram) v.getTag()).getId();
-                if (DEBUG) Log.d(TAG, "Play Related Recording:" + programId);
-                Intent intent = new Intent(getContext(), DvrPlaybackActivity.class);
-                intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, programId);
-                getContext().startActivity(intent);
-            }
-        };
-    }
-
-    @Override
-    protected String getDescription(RecordedProgram program) {
-        String description = program.getDescription();
-        if (TextUtils.isEmpty(description)) {
-            description =
-                    getContext().getResources().getString(R.string.dvr_msg_no_program_description);
-        }
-        return description;
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DvrPlaybackOverlayFragment.java b/src/com/android/tv/dvr/ui/DvrPlaybackOverlayFragment.java
deleted file mode 100644
index 51ec93b..0000000
--- a/src/com/android/tv/dvr/ui/DvrPlaybackOverlayFragment.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Point;
-import android.hardware.display.DisplayManager;
-import android.media.tv.TvContentRating;
-import android.os.Bundle;
-import android.media.session.PlaybackState;
-import android.media.tv.TvInputManager;
-import android.media.tv.TvView;
-import android.support.v17.leanback.app.PlaybackOverlayFragment;
-import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.ClassPresenterSelector;
-import android.support.v17.leanback.widget.HeaderItem;
-import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.PlaybackControlsRow;
-import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
-import android.support.v17.leanback.widget.SinglePresenterSelector;
-import android.view.Display;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.Toast;
-import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.data.BaseProgram;
-import com.android.tv.dvr.RecordedProgram;
-import com.android.tv.dialog.PinDialogFragment;
-import com.android.tv.dvr.DvrDataManager;
-import com.android.tv.dvr.DvrPlayer;
-import com.android.tv.dvr.DvrPlaybackMediaSessionHelper;
-import com.android.tv.parental.ContentRatingsManager;
-import com.android.tv.util.Utils;
-
-public class DvrPlaybackOverlayFragment extends PlaybackOverlayFragment {
-    // TODO: Handles audio focus. Deals with block and ratings.
-    private static final String TAG = "DvrPlaybackOverlayFragment";
-    private static final boolean DEBUG = false;
-
-    private static final String MEDIA_SESSION_TAG = "com.android.tv.dvr.mediasession";
-    private static final float DISPLAY_ASPECT_RATIO_EPSILON = 0.01f;
-
-    // mProgram is only used to store program from intent. Don't use it elsewhere.
-    private RecordedProgram mProgram;
-    private DvrPlaybackMediaSessionHelper mMediaSessionHelper;
-    private DvrPlaybackControlHelper mPlaybackControlHelper;
-    private ArrayObjectAdapter mRowsAdapter;
-    private SortedArrayAdapter<BaseProgram> mRelatedRecordingsRowAdapter;
-    private DvrPlaybackCardPresenter mRelatedRecordingCardPresenter;
-    private DvrDataManager mDvrDataManager;
-    private ContentRatingsManager mContentRatingsManager;
-    private TvView mTvView;
-    private View mBlockScreenView;
-    private ListRow mRelatedRecordingsRow;
-    private int mExtraPaddingNoRelatedRow;
-    private int mWindowWidth;
-    private int mWindowHeight;
-    private float mAppliedAspectRatio;
-    private float mWindowAspectRatio;
-    private boolean mPinChecked;
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        if (DEBUG) Log.d(TAG, "onCreate");
-        super.onCreate(savedInstanceState);
-        mExtraPaddingNoRelatedRow = getActivity().getResources()
-                .getDimensionPixelOffset(R.dimen.dvr_playback_fragment_extra_padding_top);
-        mDvrDataManager = TvApplication.getSingletons(getActivity()).getDvrDataManager();
-        mContentRatingsManager = TvApplication.getSingletons(getContext())
-                .getTvInputManagerHelper().getContentRatingsManager();
-        mProgram = getProgramFromIntent(getActivity().getIntent());
-        if (mProgram == null) {
-            Toast.makeText(getActivity(), getString(R.string.dvr_program_not_found),
-                    Toast.LENGTH_SHORT).show();
-            getActivity().finish();
-            return;
-        }
-        Point size = new Point();
-        ((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE))
-                .getDisplay(Display.DEFAULT_DISPLAY).getSize(size);
-        mWindowWidth = size.x;
-        mWindowHeight = size.y;
-        mWindowAspectRatio = mAppliedAspectRatio = (float) mWindowWidth / mWindowHeight;
-        setBackgroundType(PlaybackOverlayFragment.BG_LIGHT);
-        setFadingEnabled(true);
-    }
-
-    @Override
-    public void onActivityCreated(Bundle savedInstanceState) {
-        super.onActivityCreated(savedInstanceState);
-        mTvView = (TvView) getActivity().findViewById(R.id.dvr_tv_view);
-        mBlockScreenView = getActivity().findViewById(R.id.block_screen);
-        mMediaSessionHelper = new DvrPlaybackMediaSessionHelper(
-                getActivity(), MEDIA_SESSION_TAG, new DvrPlayer(mTvView), this);
-        mPlaybackControlHelper = new DvrPlaybackControlHelper(getActivity(), this);
-        setUpRows();
-        preparePlayback(getActivity().getIntent());
-        DvrPlayer dvrPlayer = mMediaSessionHelper.getDvrPlayer();
-        dvrPlayer.setAspectRatioChangedListener(new DvrPlayer.AspectRatioChangedListener() {
-            @Override
-            public void onAspectRatioChanged(float videoAspectRatio) {
-                updateAspectRatio(videoAspectRatio);
-            }
-        });
-        mPinChecked = getActivity().getIntent()
-                .getBooleanExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_PIN_CHECKED, false);
-        dvrPlayer.setContentBlockedListener(new DvrPlayer.ContentBlockedListener() {
-            @Override
-            public void onContentBlocked(TvContentRating rating) {
-                if (mPinChecked) {
-                    mTvView.unblockContent(rating);
-                    return;
-                }
-                mBlockScreenView.setVisibility(View.VISIBLE);
-                getActivity().getMediaController().getTransportControls().pause();
-                new PinDialogFragment(PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_DVR,
-                        new PinDialogFragment.ResultListener() {
-                            @Override
-                            public void done(boolean success) {
-                                if (success) {
-                                    mPinChecked = true;
-                                    mTvView.unblockContent(rating);
-                                    mBlockScreenView.setVisibility(View.GONE);
-                                    getActivity().getMediaController()
-                                            .getTransportControls().play();
-                                }
-                            }
-                        }, mContentRatingsManager.getDisplayNameForRating(rating))
-                        .show(getActivity().getFragmentManager(), PinDialogFragment.DIALOG_TAG);
-                }
-            });
-    }
-
-    @Override
-    public void onPause() {
-        if (DEBUG) Log.d(TAG, "onPause");
-        super.onPause();
-        if (mMediaSessionHelper.getPlaybackState() == PlaybackState.STATE_FAST_FORWARDING
-                || mMediaSessionHelper.getPlaybackState() == PlaybackState.STATE_REWINDING) {
-            getActivity().getMediaController().getTransportControls().pause();
-        }
-        if (mMediaSessionHelper.getPlaybackState() == PlaybackState.STATE_NONE) {
-            getActivity().requestVisibleBehind(false);
-        } else {
-            getActivity().requestVisibleBehind(true);
-        }
-    }
-
-    @Override
-    public void onDestroy() {
-        if (DEBUG) Log.d(TAG, "onDestroy");
-        mPlaybackControlHelper.unregisterCallback();
-        mMediaSessionHelper.release();
-        mRelatedRecordingCardPresenter.unbindAllViewHolders();
-        super.onDestroy();
-    }
-
-    /**
-     * Passes the intent to the fragment.
-     */
-    public void onNewIntent(Intent intent) {
-        mProgram = getProgramFromIntent(intent);
-        if (mProgram == null) {
-            Toast.makeText(getActivity(), getString(R.string.dvr_program_not_found),
-                    Toast.LENGTH_SHORT).show();
-            // Continue playing the original program
-            return;
-        }
-        preparePlayback(intent);
-    }
-
-    /**
-     * Should be called when windows' size is changed in order to notify DVR player
-     * to update it's view width/height and position.
-     */
-    public void onWindowSizeChanged(final int windowWidth, final int windowHeight) {
-        mWindowWidth = windowWidth;
-        mWindowHeight = windowHeight;
-        mWindowAspectRatio = (float) mWindowWidth / mWindowHeight;
-        updateAspectRatio(mAppliedAspectRatio);
-    }
-
-    public RecordedProgram getNextEpisode(RecordedProgram program) {
-        int position = mRelatedRecordingsRowAdapter.findInsertPosition(program);
-        if (position == mRelatedRecordingsRowAdapter.size()) {
-            return null;
-        } else {
-            return (RecordedProgram) mRelatedRecordingsRowAdapter.get(position);
-        }
-    }
-
-    void onMediaControllerUpdated() {
-        mRowsAdapter.notifyArrayItemRangeChanged(0, 1);
-    }
-
-    private void updateAspectRatio(float videoAspectRatio) {
-        if (Math.abs(mAppliedAspectRatio - videoAspectRatio) < DISPLAY_ASPECT_RATIO_EPSILON) {
-            // No need to change
-            return;
-        }
-        if (videoAspectRatio < mWindowAspectRatio) {
-            int newPadding = (mWindowWidth - Math.round(mWindowHeight * videoAspectRatio)) / 2;
-            ((ViewGroup) mTvView.getParent()).setPadding(newPadding, 0, newPadding, 0);
-        } else {
-            int newPadding = (mWindowHeight - Math.round(mWindowWidth / videoAspectRatio)) / 2;
-            ((ViewGroup) mTvView.getParent()).setPadding(0, newPadding, 0, newPadding);
-        }
-        mAppliedAspectRatio = videoAspectRatio;
-    }
-
-    private void preparePlayback(Intent intent) {
-        mMediaSessionHelper.setupPlayback(mProgram, getSeekTimeFromIntent(intent));
-        getActivity().getMediaController().getTransportControls().prepare();
-        updateRelatedRecordingsRow();
-    }
-
-    private void updateRelatedRecordingsRow() {
-        boolean wasEmpty = (mRelatedRecordingsRowAdapter.size() == 0);
-        mRelatedRecordingsRowAdapter.clear();
-        long programId = mProgram.getId();
-        String seriesId = mProgram.getSeriesId();
-        if (!TextUtils.isEmpty(seriesId)) {
-            if (DEBUG) Log.d(TAG, "Update related recordings with:" + seriesId);
-            for (RecordedProgram program : mDvrDataManager.getRecordedPrograms()) {
-                if (seriesId.equals(program.getSeriesId()) && programId != program.getId()) {
-                    mRelatedRecordingsRowAdapter.add(program);
-                }
-            }
-        }
-        View view = getView();
-        if (mRelatedRecordingsRowAdapter.size() == 0) {
-            mRowsAdapter.remove(mRelatedRecordingsRow);
-            view.setPadding(view.getPaddingLeft(), mExtraPaddingNoRelatedRow,
-                    view.getPaddingRight(), view.getPaddingBottom());
-        } else if (wasEmpty){
-            mRowsAdapter.add(mRelatedRecordingsRow);
-            view.setPadding(view.getPaddingLeft(), 0,
-                    view.getPaddingRight(), view.getPaddingBottom());
-        }
-    }
-
-    private void setUpRows() {
-        PlaybackControlsRowPresenter controlsRowPresenter =
-                mPlaybackControlHelper.createControlsRowAndPresenter();
-
-        ClassPresenterSelector selector = new ClassPresenterSelector();
-        selector.addClassPresenter(PlaybackControlsRow.class, controlsRowPresenter);
-        selector.addClassPresenter(ListRow.class, new ListRowPresenter());
-
-        mRowsAdapter = new ArrayObjectAdapter(selector);
-        mRowsAdapter.add(mPlaybackControlHelper.getControlsRow());
-        mRelatedRecordingsRow = getRelatedRecordingsRow();
-        setAdapter(mRowsAdapter);
-    }
-
-    private ListRow getRelatedRecordingsRow() {
-        mRelatedRecordingCardPresenter = new DvrPlaybackCardPresenter(getActivity());
-        mRelatedRecordingsRowAdapter = new RelatedRecordingsAdapter(mRelatedRecordingCardPresenter);
-        HeaderItem header = new HeaderItem(0,
-                getActivity().getString(R.string.dvr_playback_related_recordings));
-        return new ListRow(header, mRelatedRecordingsRowAdapter);
-    }
-
-    private RecordedProgram getProgramFromIntent(Intent intent) {
-        long programId = intent.getLongExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, -1);
-        return mDvrDataManager.getRecordedProgram(programId);
-    }
-
-    private long getSeekTimeFromIntent(Intent intent) {
-        return intent.getLongExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_SEEK_TIME,
-                TvInputManager.TIME_SHIFT_INVALID_TIME);
-    }
-
-    private class RelatedRecordingsAdapter extends SortedArrayAdapter<BaseProgram> {
-        RelatedRecordingsAdapter(DvrPlaybackCardPresenter presenter) {
-            super(new SinglePresenterSelector(presenter), BaseProgram.EPISODE_COMPARATOR);
-        }
-
-        @Override
-        long getId(BaseProgram item) {
-            return item.getId();
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/PrioritySettingsFragment.java b/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
similarity index 93%
rename from src/com/android/tv/dvr/ui/PrioritySettingsFragment.java
rename to src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
index 158bd82..e4cb724 100644
--- a/src/com/android/tv/dvr/ui/PrioritySettingsFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrPrioritySettingsFragment.java
@@ -20,7 +20,6 @@
 import android.content.Context;
 import android.graphics.Typeface;
 import android.os.Bundle;
-import android.support.v17.leanback.app.GuidedStepFragment;
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
 import android.support.v17.leanback.widget.GuidedAction;
 import android.support.v17.leanback.widget.GuidedActionsStylist;
@@ -33,15 +32,13 @@
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.DvrScheduleManager;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 
 import java.util.ArrayList;
 import java.util.List;
 
-/**
- * Fragment for DVR series recording settings.
- */
-public class PrioritySettingsFragment extends GuidedStepFragment {
+/** Fragment for DVR series recording settings. */
+public class DvrPrioritySettingsFragment extends TrackedGuidedStepFragment {
     /**
      * Name of series recording id starting the fragment.
      * Type: Long
@@ -124,7 +121,7 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         long actionId = action.getId();
         if (actionId == ACTION_ID_SAVE) {
             DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
@@ -156,13 +153,27 @@
     }
 
     @Override
+    public String getTrackerPrefix() {
+        return "DvrPrioritySettingsFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_ID_SAVE) {
+            return "save";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
+
+    @Override
     public void onGuidedActionFocused(GuidedAction action) {
         super.onGuidedActionFocused(action);
         if (mSelectedRecording == null) {
             return;
         }
         if (action.getId() < 0) {
-            int selectedPosition = mSeriesRecordings.indexOf(mSelectedRecording);
             mSelectedRecording = null;
             for (int i = 0; i < mSeriesRecordings.size(); ++i) {
                 updateItem(i);
@@ -248,4 +259,4 @@
             titleView.setTypeface(titleView.getTypeface(), Typeface.NORMAL);
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DvrScheduleFragment.java b/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
index da6d163..390e092 100644
--- a/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrScheduleFragment.java
@@ -32,9 +32,8 @@
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.dvr.ui.DvrConflictFragment.DvrProgramConflictFragment;
 import com.android.tv.util.Utils;
 
@@ -48,18 +47,26 @@
  */
 @TargetApi(Build.VERSION_CODES.N)
 public class DvrScheduleFragment extends DvrGuidedStepFragment {
+    /**
+     * Key for the whether to add the current program to series.
+     * Type: boolean
+     */
+    public static final String KEY_ADD_CURRENT_PROGRAM_TO_SERIES = "add_current_program_to_series";
+
     private static final String TAG = "DvrScheduleFragment";
 
     private static final int ACTION_RECORD_EPISODE = 1;
     private static final int ACTION_RECORD_SERIES = 2;
 
     private Program mProgram;
+    private boolean mAddCurrentProgramToSeries;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         Bundle args = getArguments();
         if (args != null) {
             mProgram = args.getParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM);
+            mAddCurrentProgramToSeries = args.getBoolean(KEY_ADD_CURRENT_PROGRAM_TO_SERIES, false);
         }
         DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
         SoftPreconditions.checkArgument(mProgram != null && mProgram.isEpisodic(), TAG,
@@ -109,7 +116,7 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         if (action.getId() == ACTION_RECORD_EPISODE) {
             getDvrManager().addSchedule(mProgram);
             List<ScheduledRecording> conflicts = getDvrManager().getConflictingSchedules(mProgram);
@@ -139,9 +146,28 @@
                         .build();
                 getDvrManager().updateSeriesRecording(seriesRecording);
             }
+
             DvrUiHelper.startSeriesSettingsActivity(getContext(),
-                    seriesRecording.getId(), null, true, true, true);
+                    seriesRecording.getId(), null, true, true, true,
+                    mAddCurrentProgramToSeries ? mProgram : null);
             dismissDialog();
         }
     }
+
+    @Override
+    public String getTrackerPrefix() {
+        return "DvrSmallSizedStorageErrorFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_RECORD_EPISODE) {
+            return "record-episode";
+        } else if (actionId == ACTION_RECORD_SERIES) {
+            return "record-series";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
 }
diff --git a/src/com/android/tv/dvr/ui/DvrSchedulesActivity.java b/src/com/android/tv/dvr/ui/DvrSchedulesActivity.java
deleted file mode 100644
index f6e6ac2..0000000
--- a/src/com/android/tv/dvr/ui/DvrSchedulesActivity.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.app.Activity;
-import android.app.ProgressDialog;
-import android.os.Bundle;
-import android.support.annotation.IntDef;
-
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.data.Program;
-import com.android.tv.dvr.EpisodicProgramLoadTask;
-import com.android.tv.dvr.SeriesRecording;
-import com.android.tv.dvr.SeriesRecordingScheduler;
-import com.android.tv.dvr.ui.list.DvrSchedulesFragment;
-import com.android.tv.dvr.ui.list.DvrSeriesSchedulesFragment;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Activity to show the list of recording schedules.
- */
-public class DvrSchedulesActivity extends Activity {
-    /**
-     * The key for the type of the schedules which will be listed in the list. The type of the value
-     * should be {@link ScheduleListType}.
-     */
-    public static final String KEY_SCHEDULES_TYPE = "schedules_type";
-
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({TYPE_FULL_SCHEDULE, TYPE_SERIES_SCHEDULE})
-    public @interface ScheduleListType {}
-    /**
-     * A type which means the activity will display the full scheduled recordings.
-     */
-    public static final int TYPE_FULL_SCHEDULE = 0;
-    /**
-     * A type which means the activity will display a scheduled recording list of a series
-     * recording.
-     */
-    public static final int TYPE_SERIES_SCHEDULE = 1;
-
-    @Override
-    public void onCreate(final Bundle savedInstanceState) {
-        TvApplication.setCurrentRunningProcess(this, true);
-        // Pass null to prevent automatically re-creating fragments
-        super.onCreate(null);
-        setContentView(R.layout.activity_dvr_schedules);
-        int scheduleType = getIntent().getIntExtra(KEY_SCHEDULES_TYPE, TYPE_FULL_SCHEDULE);
-        if (scheduleType == TYPE_FULL_SCHEDULE) {
-            DvrSchedulesFragment schedulesFragment = new DvrSchedulesFragment();
-            schedulesFragment.setArguments(getIntent().getExtras());
-            getFragmentManager().beginTransaction().add(
-                    R.id.fragment_container, schedulesFragment).commit();
-        } else if (scheduleType == TYPE_SERIES_SCHEDULE) {
-            final ProgressDialog dialog = ProgressDialog.show(this, null, getString(
-                    R.string.dvr_series_schedules_progress_message_reading_programs));
-            SeriesRecording seriesRecording = getIntent().getExtras()
-                    .getParcelable(DvrSeriesSchedulesFragment
-                            .SERIES_SCHEDULES_KEY_SERIES_RECORDING);
-            // To get programs faster, hold the update of the series schedules.
-            SeriesRecordingScheduler.getInstance(this).pauseUpdate();
-            new EpisodicProgramLoadTask(this, Collections.singletonList(seriesRecording)) {
-                @Override
-                protected void onPostExecute(List<Program> programs) {
-                    SeriesRecordingScheduler.getInstance(DvrSchedulesActivity.this).resumeUpdate();
-                    dialog.dismiss();
-                    Bundle args = getIntent().getExtras();
-                    args.putParcelableArrayList(DvrSeriesSchedulesFragment
-                            .SERIES_SCHEDULES_KEY_SERIES_PROGRAMS, new ArrayList<>(programs));
-                    DvrSeriesSchedulesFragment schedulesFragment = new DvrSeriesSchedulesFragment();
-                    schedulesFragment.setArguments(args);
-                    getFragmentManager().beginTransaction().add(
-                            R.id.fragment_container, schedulesFragment).commit();
-                }
-            }.setLoadCurrentProgram(true)
-                    .setLoadDisallowedProgram(true)
-                    .setLoadScheduledEpisode(true)
-                    .setIgnoreChannelOption(true)
-                    .execute();
-        } else {
-            finish();
-        }
-    }
-}
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java b/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
index f57e4b0..667af34 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesDeletionActivity.java
@@ -22,9 +22,6 @@
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.common.SoftPreconditions;
-import com.android.tv.dvr.ui.SeriesDeletionFragment;
-import com.android.tv.ui.sidepanel.SettingsFragment;
 
 /**
  * Activity to show details view in DVR.
@@ -42,7 +39,7 @@
         setContentView(R.layout.activity_dvr_series_settings);
         // Check savedInstanceState to prevent that activity is being showed with animation.
         if (savedInstanceState == null) {
-            SeriesDeletionFragment deletionFragment = new SeriesDeletionFragment();
+            DvrSeriesDeletionFragment deletionFragment = new DvrSeriesDeletionFragment();
             deletionFragment.setArguments(getIntent().getExtras());
             GuidedStepFragment.addAsRoot(this, deletionFragment, R.id.dvr_settings_view_frame);
         }
diff --git a/src/com/android/tv/dvr/ui/SeriesDeletionFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
similarity index 96%
rename from src/com/android/tv/dvr/ui/SeriesDeletionFragment.java
rename to src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
index 36e3cfc..8bf8560 100644
--- a/src/com/android/tv/dvr/ui/SeriesDeletionFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesDeletionFragment.java
@@ -33,9 +33,10 @@
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.DvrWatchedPositionManager;
-import com.android.tv.dvr.RecordedProgram;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.ui.GuidedActionsStylistWithDivider;
+import com.android.tv.util.Utils;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -47,7 +48,7 @@
 /**
  * Fragment for DVR series recording settings.
  */
-public class SeriesDeletionFragment extends GuidedStepFragment {
+public class DvrSeriesDeletionFragment extends GuidedStepFragment {
     private static final long WATCHED_TIME_UNIT_THRESHOLD = TimeUnit.MINUTES.toMillis(2);
 
     // Since recordings' IDs are used as its check actions' IDs, which are random positive numbers,
@@ -218,8 +219,8 @@
     private String getWatchedString(long watchedPositionMs, long durationMs) {
         if (durationMs > WATCHED_TIME_UNIT_THRESHOLD) {
             return getResources().getString(R.string.dvr_series_watched_info_minutes,
-                    Math.max(1, TimeUnit.MILLISECONDS.toMinutes(watchedPositionMs)),
-                    TimeUnit.MILLISECONDS.toMinutes(durationMs));
+                    Math.max(1, Utils.getRoundOffMinsFromMs(watchedPositionMs)),
+                    Utils.getRoundOffMinsFromMs(durationMs));
         } else {
             return getResources().getString(R.string.dvr_series_watched_info_seconds,
                     Math.max(1, TimeUnit.MILLISECONDS.toSeconds(watchedPositionMs)),
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
index 1173df4..2c4bb3e 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesScheduledFragment.java
@@ -25,22 +25,29 @@
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrScheduleManager;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.ui.list.DvrSchedulesActivity;
 import com.android.tv.dvr.ui.list.DvrSeriesSchedulesFragment;
 
 import java.util.List;
 
 public class DvrSeriesScheduledFragment extends DvrGuidedStepFragment {
+    /**
+     * The key for program list which will be passed to {@link DvrSeriesSchedulesFragment}.
+     * Type: List<{@link Program}>
+     */
+    public static final String SERIES_SCHEDULED_KEY_PROGRAMS = "series_scheduled_key_programs";
+
     private final static long SERIES_RECORDING_ID_NOT_SET = -1;
 
     private final static int ACTION_VIEW_SCHEDULES = 1;
 
-    private DvrScheduleManager mDvrScheduleManager;
     private SeriesRecording mSeriesRecording;
     private boolean mShowViewScheduleOption;
+    private List<Program> mPrograms;
 
     private int mSchedulesAddedCount = 0;
     private boolean mHasConflict = false;
@@ -58,22 +65,25 @@
         }
         mShowViewScheduleOption = getArguments().getBoolean(
                 DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION);
-        mDvrScheduleManager = TvApplication.getSingletons(context).getDvrScheduleManager();
         mSeriesRecording = TvApplication.getSingletons(context).getDvrDataManager()
                 .getSeriesRecording(seriesRecordingId);
         if (mSeriesRecording == null) {
             getActivity().finish();
             return;
         }
+        mPrograms = (List<Program>) BigArguments.getArgument(SERIES_SCHEDULED_KEY_PROGRAMS);
+        BigArguments.reset();
         mSchedulesAddedCount = TvApplication.getSingletons(getContext()).getDvrManager()
                 .getAvailableScheduledRecording(mSeriesRecording.getId()).size();
+        DvrScheduleManager dvrScheduleManager =
+                TvApplication.getSingletons(context).getDvrScheduleManager();
         List<ScheduledRecording> conflictingRecordings =
-                mDvrScheduleManager.getConflictingSchedules(mSeriesRecording);
+                dvrScheduleManager.getConflictingSchedules(mSeriesRecording);
         mHasConflict = !conflictingRecordings.isEmpty();
         for (ScheduledRecording recording : conflictingRecordings) {
             if (recording.getSeriesRecordingId() == mSeriesRecording.getId()) {
                 ++mInThisSeriesConflictCount;
-            } else {
+            } else if (recording.getPriority() < mSeriesRecording.getPriority()) {
                 ++mOutThisSeriesConflictCount;
             }
         }
@@ -106,45 +116,63 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         if (action.getId() == ACTION_VIEW_SCHEDULES) {
             Intent intent = new Intent(getActivity(), DvrSchedulesActivity.class);
             intent.putExtra(DvrSchedulesActivity.KEY_SCHEDULES_TYPE, DvrSchedulesActivity
                     .TYPE_SERIES_SCHEDULE);
             intent.putExtra(DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING,
                     mSeriesRecording);
+            BigArguments.reset();
+            BigArguments.setArgument(DvrSeriesSchedulesFragment
+                    .SERIES_SCHEDULES_KEY_SERIES_PROGRAMS, mPrograms);
             startActivity(intent);
         }
         getActivity().finish();
     }
 
+    @Override
+    public String getTrackerPrefix() {
+        return "DvrMissingStorageErrorFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_VIEW_SCHEDULES) {
+            return "view-schedules";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
+
     private String getDescription() {
         if (!mHasConflict) {
             return getResources().getQuantityString(
-                    R.plurals.dvr_series_recording_scheduled_no_conflict, mSchedulesAddedCount,
+                    R.plurals.dvr_series_scheduled_no_conflict, mSchedulesAddedCount,
                     mSchedulesAddedCount, mSeriesRecording.getTitle());
         } else {
             // mInThisSeriesConflictCount equals 0 and mOutThisSeriesConflictCount equals 0 means
             // mHasConflict is false. So we don't need to check that case.
             if (mInThisSeriesConflictCount != 0 && mOutThisSeriesConflictCount != 0) {
-                return getResources().getQuantityString(R.plurals
-                        .dvr_series_recording_scheduled_this_and_other_series_conflict,
+                return getResources().getQuantityString(
+                        R.plurals.dvr_series_scheduled_this_and_other_series_conflict,
                         mSchedulesAddedCount, mSchedulesAddedCount, mSeriesRecording.getTitle(),
                         mInThisSeriesConflictCount + mOutThisSeriesConflictCount);
             } else if (mInThisSeriesConflictCount != 0) {
-                return getResources().getQuantityString(R.plurals
-                        .dvr_series_recording_scheduled_only_this_series_conflict,
+                return getResources().getQuantityString(
+                        R.plurals.dvr_series_recording_scheduled_only_this_series_conflict,
                         mSchedulesAddedCount, mSchedulesAddedCount, mSeriesRecording.getTitle(),
                         mInThisSeriesConflictCount);
             } else {
                 if (mOutThisSeriesConflictCount == 1) {
-                    return getResources().getQuantityString(R.plurals
-                            .dvr_series_recording_scheduled_only_other_series_one_conflict,
+                    return getResources().getQuantityString(
+                            R.plurals.dvr_series_scheduled_only_other_series_one_conflict,
                             mSchedulesAddedCount, mSchedulesAddedCount,
                             mSeriesRecording.getTitle());
                 } else {
-                    return getResources().getQuantityString(R.plurals
-                            .dvr_series_recording_scheduled_only_other_series_conflict,
+                    return getResources().getQuantityString(
+                            R.plurals.dvr_series_scheduled_only_other_series_many_conflicts,
                             mSchedulesAddedCount, mSchedulesAddedCount, mSeriesRecording.getTitle(),
                             mOutThisSeriesConflictCount);
                 }
diff --git a/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java b/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
index 3f7671b..6dd20b3 100644
--- a/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesSettingsActivity.java
@@ -17,7 +17,6 @@
 package com.android.tv.dvr.ui;
 
 import android.app.Activity;
-import android.graphics.Color;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Bundle;
 import android.support.v17.leanback.app.GuidedStepFragment;
@@ -38,25 +37,34 @@
     /**
      * Name of the boolean flag to decide if the series recording with empty schedule and recording
      * will be removed.
+     * Type: boolean
      */
     public static final String REMOVE_EMPTY_SERIES_RECORDING = "remove_empty_series_recording";
     /**
      * Name of the boolean flag to decide if the setting fragment should be translucent.
+     * Type: boolean
      */
     public static final String IS_WINDOW_TRANSLUCENT = "windows_translucent";
     /**
-     * Name of the channel id list. If the channel list is given, we show the channels
-     * from the values in channel option.
-     * Type: Long array
+     * Name of the program list. The list contains the programs which belong to the series.
+     * Type: List<{@link com.android.tv.data.Program}>
      */
-    public static final String CHANNEL_ID_LIST = "channel_id_list";
+    public static final String PROGRAM_LIST = "program_list";
 
     /**
      * Name of the boolean flag to check if the confirm dialog should show view schedule option.
+     * Type: boolean
      */
     public static final String SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG =
             "show_view_schedule_option_in_dialog";
 
+    /**
+     * Name of the current program added to series. The current program will be recorded only when
+     * the series recording is initialized from media controller. But for other case, the current
+     * program won't be recorded.
+     */
+    public static final String CURRENT_PROGRAM = "current_program";
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         TvApplication.setCurrentRunningProcess(this, true);
@@ -66,7 +74,7 @@
         SoftPreconditions.checkArgument(seriesRecordingId != -1);
 
         if (savedInstanceState == null) {
-            SeriesSettingsFragment settingFragment = new SeriesSettingsFragment();
+            DvrSeriesSettingsFragment settingFragment = new DvrSeriesSettingsFragment();
             settingFragment.setArguments(getIntent().getExtras());
             GuidedStepFragment.addAsRoot(this, settingFragment, R.id.dvr_settings_view_frame);
         }
diff --git a/src/com/android/tv/dvr/ui/SeriesSettingsFragment.java b/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
similarity index 64%
rename from src/com/android/tv/dvr/ui/SeriesSettingsFragment.java
rename to src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
index 6c05c9c..f28382d 100644
--- a/src/com/android/tv/dvr/ui/SeriesSettingsFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrSeriesSettingsFragment.java
@@ -17,19 +17,13 @@
 package com.android.tv.dvr.ui;
 
 import android.app.FragmentManager;
-import android.app.ProgressDialog;
 import android.content.Context;
 import android.os.Bundle;
 import android.support.v17.leanback.app.GuidedStepFragment;
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
 import android.support.v17.leanback.widget.GuidedAction;
 import android.support.v17.leanback.widget.GuidedActionsStylist;
-import android.util.Log;
 import android.util.LongSparseArray;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ProgressBar;
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
@@ -38,14 +32,14 @@
 import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.EpisodicProgramLoadTask;
-import com.android.tv.dvr.SeriesRecording;
-import com.android.tv.dvr.SeriesRecording.ChannelOption;
-import com.android.tv.dvr.SeriesRecordingScheduler;
-import com.android.tv.dvr.SeriesRecordingScheduler.OnSeriesRecordingUpdatedListener;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeasonEpisodeNumber;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.data.SeriesRecording.ChannelOption;
+import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
+
 import java.util.ArrayList;
-import java.util.Comparator;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -53,7 +47,7 @@
 /**
  * Fragment for DVR series recording settings.
  */
-public class SeriesSettingsFragment extends GuidedStepFragment
+public class DvrSeriesSettingsFragment extends GuidedStepFragment
         implements DvrDataManager.SeriesRecordingListener {
     private static final String TAG = "SeriesSettingsFragment";
     private static final boolean DEBUG = false;
@@ -66,15 +60,13 @@
     private static final long SUB_ACTION_ID_CHANNEL_ONE_BASE = 500;
 
     private DvrDataManager mDvrDataManager;
-    private ChannelDataManager mChannelDataManager;
-    private DvrManager mDvrManager;
     private SeriesRecording mSeriesRecording;
     private long mSeriesRecordingId;
     @ChannelOption int mChannelOption;
-    private Comparator<Channel> mChannelComparator;
     private long mSelectedChannelId;
     private int mBackStackCount;
     private boolean mShowViewScheduleOptionInDialog;
+    private Program mCurrentProgram;
 
     private String mFragmentTitle;
     private String mProrityActionTitle;
@@ -84,7 +76,7 @@
     private String mChannelsActionAllText;
     private LongSparseArray<Channel> mId2Channel = new LongSparseArray<>();
     private List<Channel> mChannels = new ArrayList<>();
-    private EpisodicProgramLoadTask mEpisodicProgramLoadTask;
+    private List<Program> mPrograms;
 
     private GuidedAction mPriorityGuidedAction;
     private GuidedAction mChannelsGuidedAction;
@@ -100,22 +92,24 @@
             getActivity().finish();
             return;
         }
-        mDvrManager = TvApplication.getSingletons(context).getDvrManager();
         mShowViewScheduleOptionInDialog = getArguments().getBoolean(
                 DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG);
+        mCurrentProgram = getArguments().getParcelable(DvrSeriesSettingsActivity.CURRENT_PROGRAM);
         mDvrDataManager.addSeriesRecordingListener(this);
-        long[] channelIds = getArguments().getLongArray(DvrSeriesSettingsActivity.CHANNEL_ID_LIST);
-        mChannelDataManager = TvApplication.getSingletons(context).getChannelDataManager();
-        if (channelIds == null) {
-            Channel channel = mChannelDataManager.getChannel(mSeriesRecording.getChannelId());
-            if (channel != null) {
-                mId2Channel.put(channel.getId(), channel);
-                mChannels.add(channel);
-            }
-            collectChannelsInBackground();
-        } else {
-            for (long channelId : channelIds) {
-                Channel channel = mChannelDataManager.getChannel(channelId);
+        mPrograms = (List<Program>) BigArguments.getArgument(
+                DvrSeriesSettingsActivity.PROGRAM_LIST);
+        BigArguments.reset();
+        if (mPrograms == null) {
+            getActivity().finish();
+            return;
+        }
+        Set<Long> channelIds = new HashSet<>();
+        ChannelDataManager channelDataManager =
+                TvApplication.getSingletons(context).getChannelDataManager();
+        for (Program program : mPrograms) {
+            long channelId = program.getChannelId();
+            if (channelIds.add(channelId)) {
+                Channel channel = channelDataManager.getChannel(channelId);
                 if (channel != null) {
                     mId2Channel.put(channel.getId(), channel);
                     mChannels.add(channel);
@@ -125,16 +119,14 @@
         mChannelOption = mSeriesRecording.getChannelOption();
         mSelectedChannelId = Channel.INVALID_ID;
         if (mChannelOption == SeriesRecording.OPTION_CHANNEL_ONE) {
-            Channel channel = mChannelDataManager.getChannel(mSeriesRecording.getChannelId());
+            Channel channel = channelDataManager.getChannel(mSeriesRecording.getChannelId());
             if (channel != null) {
                 mSelectedChannelId = channel.getId();
             } else {
                 mChannelOption = SeriesRecording.OPTION_CHANNEL_ALL;
             }
         }
-        mChannelComparator = new Channel.DefaultComparator(context,
-                TvApplication.getSingletons(context).getTvInputManagerHelper());
-        mChannels.sort(mChannelComparator);
+        mChannels.sort(Channel.CHANNEL_NUMBER_COMPARATOR);
         mFragmentTitle = getString(R.string.dvr_series_settings_title);
         mProrityActionTitle = getString(R.string.dvr_series_settings_priority);
         mProrityActionHighestText = getString(R.string.dvr_series_settings_priority_highest);
@@ -144,23 +136,23 @@
     }
 
     @Override
+    public void onResume() {
+        super.onResume();
+        // To avoid the order of series's priority has changed, but series doesn't get update.
+        updatePriorityGuidedAction();
+    }
+
+    @Override
     public void onDetach() {
         super.onDetach();
         mDvrDataManager.removeSeriesRecordingListener(this);
-        if (mEpisodicProgramLoadTask != null) {
-            mEpisodicProgramLoadTask.cancel(true);
-            mEpisodicProgramLoadTask = null;
-        }
     }
 
     @Override
     public void onDestroy() {
-        DvrManager dvrManager = TvApplication.getSingletons(getActivity()).getDvrManager();
-        if (getFragmentManager().getBackStackEntryCount() == mBackStackCount
-                && getArguments()
-                        .getBoolean(DvrSeriesSettingsActivity.REMOVE_EMPTY_SERIES_RECORDING)
-                && dvrManager.canRemoveSeriesRecording(mSeriesRecordingId)) {
-            dvrManager.removeSeriesRecording(mSeriesRecordingId);
+        if (getFragmentManager().getBackStackEntryCount() == mBackStackCount && getArguments()
+                .getBoolean(DvrSeriesSettingsActivity.REMOVE_EMPTY_SERIES_RECORDING)) {
+            mDvrDataManager.checkAndRemoveEmptySeriesRecording(mSeriesRecordingId);
         }
         super.onDestroy();
     }
@@ -178,7 +170,6 @@
                 .id(ACTION_ID_PRIORITY)
                 .title(mProrityActionTitle)
                 .build();
-        updatePriorityGuidedAction(false);
         actions.add(mPriorityGuidedAction);
 
         mChannelsGuidedAction = new GuidedAction.Builder(getActivity())
@@ -204,10 +195,6 @@
     public void onGuidedActionClicked(GuidedAction action) {
         long actionId = action.getId();
         if (actionId == GuidedAction.ACTION_ID_OK) {
-            if (mEpisodicProgramLoadTask != null) {
-                mEpisodicProgramLoadTask.cancel(true);
-                mEpisodicProgramLoadTask = null;
-            }
             if (mChannelOption != mSeriesRecording.getChannelOption()
                     || mSeriesRecording.isStopped()
                     || (mChannelOption == SeriesRecording.OPTION_CHANNEL_ONE
@@ -218,28 +205,14 @@
                 if (mSelectedChannelId != Channel.INVALID_ID) {
                     builder.setChannelId(mSelectedChannelId);
                 }
-                TvApplication.getSingletons(getContext()).getDvrManager()
-                        .updateSeriesRecording(builder.build());
-                SeriesRecordingScheduler scheduler =
-                        SeriesRecordingScheduler.getInstance(getContext());
-                // Since dialog is used even after the fragment is closed, we should
-                // use application context.
-                ProgressDialog dialog = ProgressDialog.show(getContext(), null, getString(
-                                R.string.dvr_series_schedules_progress_message_updating_programs));
-                scheduler.addOnSeriesRecordingUpdatedListener(
-                        new OnSeriesRecordingUpdatedListener() {
-                    @Override
-                    public void onSeriesRecordingUpdated(SeriesRecording... seriesRecordings) {
-                        for (SeriesRecording seriesRecording : seriesRecordings) {
-                            if (seriesRecording.getId() == mSeriesRecordingId) {
-                                dialog.dismiss();
-                                scheduler.removeOnSeriesRecordingUpdatedListener(this);
-                                showConfirmDialog();
-                                return;
-                            }
-                        }
-                    }
-                });
+                DvrManager dvrManager = TvApplication.getSingletons(getContext()).getDvrManager();
+                        dvrManager.updateSeriesRecording(builder.build());
+                if (mCurrentProgram != null && (mChannelOption == SeriesRecording.OPTION_CHANNEL_ALL
+                        || mSelectedChannelId == mCurrentProgram.getChannelId())) {
+                    dvrManager.addSchedule(mCurrentProgram);
+                }
+                updateSchedulesToSeries();
+                showConfirmDialog();
             } else {
                 showConfirmDialog();
             }
@@ -247,9 +220,9 @@
             finishGuidedStepFragments();
         } else if (actionId == ACTION_ID_PRIORITY) {
             FragmentManager fragmentManager = getFragmentManager();
-            PrioritySettingsFragment fragment = new PrioritySettingsFragment();
+            DvrPrioritySettingsFragment fragment = new DvrPrioritySettingsFragment();
             Bundle args = new Bundle();
-            args.putLong(PrioritySettingsFragment.COME_FROM_SERIES_RECORDING_ID,
+            args.putLong(DvrPrioritySettingsFragment.COME_FROM_SERIES_RECORDING_ID,
                     mSeriesRecording.getId());
             fragment.setArguments(args);
             GuidedStepFragment.add(fragmentManager, fragment, R.id.dvr_settings_view_frame);
@@ -281,7 +254,7 @@
     private void updateChannelsGuidedAction(boolean notifyActionChanged) {
         if (mChannelOption == SeriesRecording.OPTION_CHANNEL_ALL) {
             mChannelsGuidedAction.setDescription(mChannelsActionAllText);
-        } else {
+        } else if (mId2Channel.get(mSelectedChannelId) != null){
             mChannelsGuidedAction.setDescription(mId2Channel.get(mSelectedChannelId)
                     .getDisplayText());
         }
@@ -290,7 +263,7 @@
         }
     }
 
-    private void updatePriorityGuidedAction(boolean notifyActionChanged) {
+    private void updatePriorityGuidedAction() {
         int totalSeriesCount = 0;
         int priorityOrder = 0;
         for (SeriesRecording seriesRecording : mDvrDataManager.getSeriesRecordings()) {
@@ -312,49 +285,38 @@
             mPriorityGuidedAction.setDescription(getString(
                     R.string.dvr_series_settings_priority_rank, priorityOrder + 1));
         }
-        if (notifyActionChanged) {
-            notifyActionChanged(findActionPositionById(ACTION_ID_PRIORITY));
-        }
+        notifyActionChanged(findActionPositionById(ACTION_ID_PRIORITY));
     }
 
-    private void collectChannelsInBackground() {
-        if (mEpisodicProgramLoadTask != null) {
-            mEpisodicProgramLoadTask.cancel(true);
-        }
-        mEpisodicProgramLoadTask = new EpisodicProgramLoadTask(getContext(), mSeriesRecording) {
-            @Override
-            protected void onPostExecute(List<Program> programs) {
-                mEpisodicProgramLoadTask = null;
-                Set<Long> channelIds = new HashSet<>();
-                for (Program program : programs) {
-                    channelIds.add(program.getChannelId());
-                }
-                boolean channelAdded = false;
-                for (Long channelId : channelIds) {
-                    if (mId2Channel.get(channelId) != null) {
-                        continue;
-                    }
-                    Channel channel = mChannelDataManager.getChannel(channelId);
-                    if (channel != null) {
-                        channelAdded = true;
-                        mId2Channel.put(channelId, channel);
-                        mChannels.add(channel);
-                        if (DEBUG) Log.d(TAG, "Added channel: " + channel);
-                    }
-                }
-                if (!channelAdded) {
-                    return;
-                }
-                mChannels.sort(mChannelComparator);
-                mChannelsGuidedAction.setSubActions(buildChannelSubAction());
-                notifyActionChanged(findActionPositionById(ACTION_ID_CHANNEL));
-                if (DEBUG) Log.d(TAG, "Complete EpisodicProgramLoadTask");
+    private void updateSchedulesToSeries() {
+        List<Program> recordingCandidates = new ArrayList<>();
+        Set<SeasonEpisodeNumber> scheduledEpisodes = new HashSet<>();
+        for (ScheduledRecording r : mDvrDataManager.getScheduledRecordings(mSeriesRecordingId)) {
+            if (r.getState() != ScheduledRecording.STATE_RECORDING_FAILED
+                    && r.getState() != ScheduledRecording.STATE_RECORDING_CLIPPED) {
+                scheduledEpisodes.add(new SeasonEpisodeNumber(
+                        r.getSeriesRecordingId(), r.getSeasonNumber(), r.getEpisodeNumber()));
             }
-        }.setLoadCurrentProgram(true)
-                .setLoadDisallowedProgram(true)
-                .setLoadScheduledEpisode(true)
-                .setIgnoreChannelOption(true);
-        mEpisodicProgramLoadTask.execute();
+        }
+        for (Program program : mPrograms) {
+            // Removes current programs and scheduled episodes out, matches the channel option.
+            if (program.getStartTimeUtcMillis() >= System.currentTimeMillis()
+                    && mSeriesRecording.matchProgram(program)
+                    && !scheduledEpisodes.contains(new SeasonEpisodeNumber(
+                    mSeriesRecordingId, program.getSeasonNumber(), program.getEpisodeNumber()))) {
+                recordingCandidates.add(program);
+            }
+        }
+        if (recordingCandidates.isEmpty()) {
+            return;
+        }
+        List<Program> programsToSchedule = SeriesRecordingScheduler.pickOneProgramPerEpisode(
+                mDvrDataManager, Collections.singletonList(mSeriesRecording), recordingCandidates)
+                .get(mSeriesRecordingId);
+        if (!programsToSchedule.isEmpty()) {
+            TvApplication.getSingletons(getContext()).getDvrManager()
+                    .addScheduleToSeriesRecording(mSeriesRecording, programsToSchedule);
+        }
     }
 
     private List<GuidedAction> buildChannelSubAction() {
@@ -373,8 +335,8 @@
     }
 
     private void showConfirmDialog() {
-        DvrUiHelper.StartSeriesScheduledDialogActivity(
-                getContext(), mSeriesRecording, mShowViewScheduleOptionInDialog);
+        DvrUiHelper.StartSeriesScheduledDialogActivity(getContext(), mSeriesRecording,
+                mShowViewScheduleOptionInDialog, mPrograms);
         finishGuidedStepFragments();
     }
 
@@ -382,16 +344,23 @@
     public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) { }
 
     @Override
-    public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) { }
+    public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
+        for (SeriesRecording series : seriesRecordings) {
+            if (series.getId() == mSeriesRecording.getId()) {
+                finishGuidedStepFragments();
+                return;
+            }
+        }
+    }
 
     @Override
     public void onSeriesRecordingChanged(SeriesRecording... seriesRecordings) {
         for (SeriesRecording seriesRecording : seriesRecordings) {
             if (seriesRecording.getId() == mSeriesRecordingId) {
                 mSeriesRecording = seriesRecording;
-                updatePriorityGuidedAction(true);
+                updatePriorityGuidedAction();
                 return;
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java b/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
index c386788..baa4579 100644
--- a/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrStopRecordingFragment.java
@@ -25,15 +25,12 @@
 import android.support.annotation.NonNull;
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
 import android.support.v17.leanback.widget.GuidedAction;
-import android.text.TextUtils;
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.data.Channel;
-import com.android.tv.data.ChannelDataManager;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -131,15 +128,8 @@
         String title = getString(R.string.dvr_stop_recording_dialog_title);
         String description;
         if (mStopReason == REASON_ON_CONFLICT) {
-            String programTitle = mSchedule.getProgramTitle();
-            if (TextUtils.isEmpty(programTitle)) {
-                ChannelDataManager channelDataManager =
-                        TvApplication.getSingletons(getActivity()).getChannelDataManager();
-                Channel channel = channelDataManager.getChannel(mSchedule.getChannelId());
-                programTitle = channel.getDisplayName();
-            }
             description = getString(R.string.dvr_stop_recording_dialog_description_on_conflict,
-                    mSchedule.getProgramTitle());
+                    mSchedule.getProgramDisplayTitle(getContext()));
         } else {
             description = getString(R.string.dvr_stop_recording_dialog_description);
         }
@@ -158,4 +148,19 @@
                 .clickAction(GuidedAction.ACTION_ID_CANCEL)
                 .build());
     }
+
+    @Override
+    public String getTrackerPrefix() {
+        return "DvrStopRecordingFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == ACTION_STOP) {
+            return "stop";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
index feaa235..7b56cfc 100644
--- a/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
+++ b/src/com/android/tv/dvr/ui/DvrStopSeriesRecordingFragment.java
@@ -31,8 +31,8 @@
 import com.android.tv.TvApplication;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -78,7 +78,7 @@
     }
 
     @Override
-    public void onGuidedActionClicked(GuidedAction action) {
+    public void onTrackedGuidedActionClicked(GuidedAction action) {
         if (action.getId() == ACTION_STOP_SERIES_RECORDING) {
             ApplicationSingletons singletons = TvApplication.getSingletons(getContext());
             DvrManager dvrManager = singletons.getDvrManager();
@@ -101,4 +101,18 @@
         }
         dismissDialog();
     }
+
+    @Override
+    public String getTrackerPrefix() {
+        return "DvrStopSeriesRecordingFragment";
+    }
+
+    @Override
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        if (action.getId() == ACTION_STOP_SERIES_RECORDING) {
+            return "stop";
+        } else {
+            return super.getTrackerLabelForGuidedAction(action);
+        }
+    }
 }
diff --git a/src/com/android/tv/dvr/ui/DvrUiHelper.java b/src/com/android/tv/dvr/ui/DvrUiHelper.java
new file mode 100644
index 0000000..302fd6c
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/DvrUiHelper.java
@@ -0,0 +1,649 @@
+/*
+ * 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.dvr.ui;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.media.tv.TvInputManager;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.MainThread;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.ActivityOptionsCompat;
+import android.text.Html;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.TextUtils;
+import android.text.style.TextAppearanceSpan;
+import android.widget.ImageView;
+import android.widget.Toast;
+
+import com.android.tv.MainActivity;
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.common.SoftPreconditions;
+import com.android.tv.data.BaseProgram;
+import com.android.tv.data.Channel;
+import com.android.tv.data.Program;
+import com.android.tv.dialog.HalfSizedDialogFragment;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.DvrStorageStatusManager;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrAlreadyRecordedDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrAlreadyScheduledDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrChannelRecordDurationOptionDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrChannelWatchConflictDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrInsufficientSpaceErrorDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrMissingStorageErrorDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrNoFreeSpaceErrorDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrProgramConflictDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrScheduleDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrSmallSizedStorageErrorDialogFragment;
+import com.android.tv.dvr.ui.DvrHalfSizedDialogFragment.DvrStopRecordingDialogFragment;
+import com.android.tv.dvr.ui.browse.DvrBrowseActivity;
+import com.android.tv.dvr.ui.browse.DvrDetailsActivity;
+import com.android.tv.dvr.ui.list.DvrSchedulesActivity;
+import com.android.tv.dvr.ui.list.DvrSchedulesFragment;
+import com.android.tv.dvr.ui.list.DvrSeriesSchedulesFragment;
+import com.android.tv.dvr.ui.playback.DvrPlaybackActivity;
+import com.android.tv.util.ToastUtils;
+import com.android.tv.util.Utils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A helper class for DVR UI.
+ */
+@MainThread
+@TargetApi(Build.VERSION_CODES.N)
+public class DvrUiHelper {
+    private static final String TAG = "DvrUiHelper";
+
+    private static ProgressDialog sProgressDialog = null;
+
+    /**
+     * Checks if the storage status is good for recording and shows error messages if needed.
+     *
+     * @param recordingRequestRunnable if the storage status is OK to record or users choose to
+     *                                 perform the operation anyway, this Runnable will run.
+     */
+    public static void checkStorageStatusAndShowErrorMessage(Activity activity, String inputId,
+            Runnable recordingRequestRunnable) {
+        if (Utils.isBundledInput(inputId)) {
+            switch (TvApplication.getSingletons(activity).getDvrStorageStatusManager()
+                    .getDvrStorageStatus()) {
+                case DvrStorageStatusManager.STORAGE_STATUS_TOTAL_CAPACITY_TOO_SMALL:
+                    showDvrSmallSizedStorageErrorDialog(activity);
+                    return;
+                case DvrStorageStatusManager.STORAGE_STATUS_MISSING:
+                    showDvrMissingStorageErrorDialog(activity);
+                    return;
+                case DvrStorageStatusManager.STORAGE_STATUS_FREE_SPACE_INSUFFICIENT:
+                    showDvrNoFreeSpaceErrorDialog(activity, recordingRequestRunnable);
+                    return;
+            }
+        }
+        recordingRequestRunnable.run();
+    }
+
+    /**
+     * Shows the schedule dialog.
+     */
+    public static void showScheduleDialog(Activity activity, Program program,
+            boolean addCurrentProgramToSeries) {
+        if (SoftPreconditions.checkNotNull(program) == null) {
+            return;
+        }
+        Bundle args = new Bundle();
+        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
+        args.putBoolean(DvrScheduleFragment.KEY_ADD_CURRENT_PROGRAM_TO_SERIES,
+                addCurrentProgramToSeries);
+        showDialogFragment(activity, new DvrScheduleDialogFragment(), args, true, true);
+    }
+
+    /**
+     * Shows the recording duration options dialog.
+     */
+    public static void showChannelRecordDurationOptions(Activity activity, Channel channel) {
+        if (SoftPreconditions.checkNotNull(channel) == null) {
+            return;
+        }
+        Bundle args = new Bundle();
+        args.putLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID, channel.getId());
+        showDialogFragment(activity, new DvrChannelRecordDurationOptionDialogFragment(), args);
+    }
+
+    /**
+     * Shows the dialog which says that the new schedule conflicts with others.
+     */
+    public static void showScheduleConflictDialog(Activity activity, Program program) {
+        if (program == null) {
+            return;
+        }
+        Bundle args = new Bundle();
+        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
+        showDialogFragment(activity, new DvrProgramConflictDialogFragment(), args, false, true);
+    }
+
+    /**
+     * Shows the conflict dialog for the channel watching.
+     */
+    public static void showChannelWatchConflictDialog(MainActivity activity, Channel channel) {
+        if (channel == null) {
+            return;
+        }
+        Bundle args = new Bundle();
+        args.putLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID, channel.getId());
+        showDialogFragment(activity, new DvrChannelWatchConflictDialogFragment(), args);
+    }
+
+    /**
+     * Shows DVR insufficient space error dialog.
+     */
+    public static void showDvrInsufficientSpaceErrorDialog(MainActivity activity,
+            Set<String> failedScheduledRecordingInfoSet) {
+        Bundle args = new Bundle();
+        ArrayList<String> failedScheduledRecordingInfoArray =
+                new ArrayList<>(failedScheduledRecordingInfoSet);
+        args.putStringArrayList(DvrInsufficientSpaceErrorFragment.FAILED_SCHEDULED_RECORDING_INFOS,
+                failedScheduledRecordingInfoArray);
+        showDialogFragment(activity, new DvrInsufficientSpaceErrorDialogFragment(), args);
+        Utils.clearRecordingFailedReason(activity,
+                TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE);
+        Utils.clearFailedScheduledRecordingInfoSet(activity);
+    }
+
+    /**
+     * Shows DVR no free space error dialog.
+     *
+     * @param recordingRequestRunnable the recording request to be executed when users choose
+     *                                 {@link DvrGuidedStepFragment#ACTION_RECORD_ANYWAY}.
+     */
+    public static void showDvrNoFreeSpaceErrorDialog(Activity activity,
+            Runnable recordingRequestRunnable) {
+        DvrHalfSizedDialogFragment fragment = new DvrNoFreeSpaceErrorDialogFragment();
+        fragment.setOnActionClickListener(new HalfSizedDialogFragment.OnActionClickListener() {
+            @Override
+            public void onActionClick(long actionId) {
+                if (actionId == DvrGuidedStepFragment.ACTION_RECORD_ANYWAY) {
+                    recordingRequestRunnable.run();
+                } else if (actionId == DvrGuidedStepFragment.ACTION_DELETE_RECORDINGS) {
+                    Intent intent = new Intent(activity, DvrBrowseActivity.class);
+                    activity.startActivity(intent);
+                }
+            }
+        });
+        showDialogFragment(activity, fragment, null);
+    }
+
+    /**
+     * Shows DVR missing storage error dialog.
+     */
+    private static void showDvrMissingStorageErrorDialog(Activity activity) {
+        showDialogFragment(activity, new DvrMissingStorageErrorDialogFragment(), null);
+    }
+
+    /**
+     * Shows DVR small sized storage error dialog.
+     */
+    public static void showDvrSmallSizedStorageErrorDialog(Activity activity) {
+        showDialogFragment(activity, new DvrSmallSizedStorageErrorDialogFragment(), null);
+    }
+
+    /**
+     * Shows stop recording dialog.
+     */
+    public static void showStopRecordingDialog(Activity activity, long channelId, int reason,
+            HalfSizedDialogFragment.OnActionClickListener listener) {
+        Bundle args = new Bundle();
+        args.putLong(DvrHalfSizedDialogFragment.KEY_CHANNEL_ID, channelId);
+        args.putInt(DvrStopRecordingFragment.KEY_REASON, reason);
+        DvrHalfSizedDialogFragment fragment = new DvrStopRecordingDialogFragment();
+        fragment.setOnActionClickListener(listener);
+        showDialogFragment(activity, fragment, args);
+    }
+
+    /**
+     * Shows "already scheduled" dialog.
+     */
+    public static void showAlreadyScheduleDialog(Activity activity, Program program) {
+        if (program == null) {
+            return;
+        }
+        Bundle args = new Bundle();
+        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
+        showDialogFragment(activity, new DvrAlreadyScheduledDialogFragment(), args, false, true);
+    }
+
+    /**
+     * Shows "already recorded" dialog.
+     */
+    public static void showAlreadyRecordedDialog(Activity activity, Program program) {
+        if (program == null) {
+            return;
+        }
+        Bundle args = new Bundle();
+        args.putParcelable(DvrHalfSizedDialogFragment.KEY_PROGRAM, program);
+        showDialogFragment(activity, new DvrAlreadyRecordedDialogFragment(), args, false, true);
+    }
+
+    /**
+     * Handle the request of recording a current program. It will handle creating schedules and
+     * shows the proper dialog and toast message respectively for timed-recording and program
+     * recording cases.
+     *
+     * @param addProgramToSeries denotes whether the program to be recorded should be added into
+     *                           the series recording when users choose to record the entire series.
+     */
+    public static void requestRecordingCurrentProgram(Activity activity,
+            Channel channel, Program program, boolean addProgramToSeries) {
+        if (program == null) {
+            DvrUiHelper.showChannelRecordDurationOptions(activity, channel);
+        } else if (DvrUiHelper.handleCreateSchedule(activity, program, addProgramToSeries)) {
+            String msg = activity.getString(R.string.dvr_msg_current_program_scheduled,
+                    program.getTitle(), Utils.toTimeString(program.getEndTimeUtcMillis(), false));
+            Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    /**
+     * Handle the request of recording a future program. It will handle creating schedules and
+     * shows the proper toast message.
+     *
+     * @param addProgramToSeries denotes whether the program to be recorded should be added into
+     *                           the series recording when users choose to record the entire series.
+     */
+    public static void requestRecordingFutureProgram(Activity activity,
+            Program program, boolean addProgramToSeries) {
+        if (DvrUiHelper.handleCreateSchedule(activity, program, addProgramToSeries)) {
+            String msg = activity.getString(
+                    R.string.dvr_msg_program_scheduled, program.getTitle());
+            ToastUtils.show(activity, msg, Toast.LENGTH_SHORT);
+        }
+    }
+
+    /**
+     * Handles the action to create the new schedule. It returns {@code true} if the schedule is
+     * added and there's no additional UI, otherwise {@code false}.
+     */
+    private static boolean handleCreateSchedule(Activity activity, Program program,
+            boolean addProgramToSeries) {
+        if (program == null) {
+            return false;
+        }
+        DvrManager dvrManager = TvApplication.getSingletons(activity).getDvrManager();
+        if (!program.isEpisodic()) {
+            // One time recording.
+            dvrManager.addSchedule(program);
+            if (!dvrManager.getConflictingSchedules(program).isEmpty()) {
+                DvrUiHelper.showScheduleConflictDialog(activity, program);
+                return false;
+            }
+        } else {
+            // Show recorded program rather than the schedule.
+            RecordedProgram recordedProgram = dvrManager.getRecordedProgram(program.getTitle(),
+                    program.getSeasonNumber(), program.getEpisodeNumber());
+            if (recordedProgram != null) {
+                DvrUiHelper.showAlreadyRecordedDialog(activity, program);
+                return false;
+            }
+            ScheduledRecording duplicate = dvrManager.getScheduledRecording(program.getTitle(),
+                    program.getSeasonNumber(), program.getEpisodeNumber());
+            if (duplicate != null
+                    && (duplicate.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED
+                    || duplicate.getState()
+                    == ScheduledRecording.STATE_RECORDING_IN_PROGRESS)) {
+                DvrUiHelper.showAlreadyScheduleDialog(activity, program);
+                return false;
+            }
+            SeriesRecording seriesRecording = dvrManager.getSeriesRecording(program);
+            if (seriesRecording == null || seriesRecording.isStopped()) {
+                DvrUiHelper.showScheduleDialog(activity, program, addProgramToSeries);
+                return false;
+            } else {
+                // Just add the schedule.
+                dvrManager.addSchedule(program);
+            }
+        }
+        return true;
+    }
+
+    private static void showDialogFragment(Activity activity,
+            DvrHalfSizedDialogFragment dialogFragment, Bundle args) {
+        showDialogFragment(activity, dialogFragment, args, false, false);
+    }
+
+    private static void showDialogFragment(Activity activity,
+            DvrHalfSizedDialogFragment dialogFragment, Bundle args, boolean keepSidePanelHistory,
+            boolean keepProgramGuide) {
+        dialogFragment.setArguments(args);
+        if (activity instanceof MainActivity) {
+            ((MainActivity) activity).getOverlayManager()
+                    .showDialogFragment(DvrHalfSizedDialogFragment.DIALOG_TAG, dialogFragment,
+                            keepSidePanelHistory, keepProgramGuide);
+        } else {
+            dialogFragment.show(activity.getFragmentManager(),
+                    DvrHalfSizedDialogFragment.DIALOG_TAG);
+        }
+    }
+
+    /**
+     * Checks whether channel watch conflict dialog is open or not.
+     */
+    public static boolean isChannelWatchConflictDialogShown(MainActivity activity) {
+        return activity.getOverlayManager().getCurrentDialog() instanceof
+                DvrChannelWatchConflictDialogFragment;
+    }
+
+    private static ScheduledRecording getEarliestScheduledRecording(List<ScheduledRecording>
+            recordings) {
+        ScheduledRecording earlistScheduledRecording = null;
+        if (!recordings.isEmpty()) {
+            Collections.sort(recordings,
+                    ScheduledRecording.START_TIME_THEN_PRIORITY_THEN_ID_COMPARATOR);
+            earlistScheduledRecording = recordings.get(0);
+        }
+        return earlistScheduledRecording;
+    }
+
+    /**
+     * Launches DVR playback activity for the give recorded program.
+     *
+     * @param programId the ID of the recorded program going to be played.
+     * @param seekTimeMs the seek position to initial playback.
+     * @param pinChecked {@code true} if the pin code for parental controls has already been
+     *                   verified, otherwise {@code false}.
+     */
+    public static void startPlaybackActivity(Context context, long programId,
+            long seekTimeMs, boolean pinChecked) {
+        Intent intent = new Intent(context, DvrPlaybackActivity.class);
+        intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, programId);
+        if (seekTimeMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
+            intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_SEEK_TIME, seekTimeMs);
+        }
+        intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_PIN_CHECKED, pinChecked);
+        context.startActivity(intent);
+    }
+
+    /**
+     * Shows the schedules activity to resolve the tune conflict.
+     */
+    public static void startSchedulesActivityForTuneConflict(Context context, Channel channel) {
+        if (channel == null) {
+            return;
+        }
+        List<ScheduledRecording> conflicts = TvApplication.getSingletons(context).getDvrManager()
+                .getConflictingSchedulesForTune(channel.getId());
+        startSchedulesActivity(context, getEarliestScheduledRecording(conflicts));
+    }
+
+    /**
+     * Shows the schedules activity to resolve the one time recording conflict.
+     */
+    public static void startSchedulesActivityForOneTimeRecordingConflict(Context context,
+            List<ScheduledRecording> conflicts) {
+        startSchedulesActivity(context, getEarliestScheduledRecording(conflicts));
+    }
+
+    /**
+     * Shows the schedules activity with full schedule.
+     */
+    public static void startSchedulesActivity(Context context, ScheduledRecording
+            focusedScheduledRecording) {
+        Intent intent = new Intent(context, DvrSchedulesActivity.class);
+        intent.putExtra(DvrSchedulesActivity.KEY_SCHEDULES_TYPE,
+                DvrSchedulesActivity.TYPE_FULL_SCHEDULE);
+        if (focusedScheduledRecording != null) {
+            intent.putExtra(DvrSchedulesFragment.SCHEDULES_KEY_SCHEDULED_RECORDING,
+                    focusedScheduledRecording);
+        }
+        context.startActivity(intent);
+    }
+
+    /**
+     * Shows the schedules activity for series recording.
+     */
+    public static void startSchedulesActivityForSeries(Context context,
+            SeriesRecording seriesRecording) {
+        Intent intent = new Intent(context, DvrSchedulesActivity.class);
+        intent.putExtra(DvrSchedulesActivity.KEY_SCHEDULES_TYPE,
+                DvrSchedulesActivity.TYPE_SERIES_SCHEDULE);
+        intent.putExtra(DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_RECORDING,
+                seriesRecording);
+        context.startActivity(intent);
+    }
+
+    /**
+     * Shows the series settings activity.
+     *
+     * @param programs list of programs which belong to the series.
+     */
+    public static void startSeriesSettingsActivity(Context context, long seriesRecordingId,
+            @Nullable List<Program> programs, boolean removeEmptySeriesSchedule,
+            boolean isWindowTranslucent, boolean showViewScheduleOptionInDialog,
+            Program currentProgram) {
+        SeriesRecording series = TvApplication.getSingletons(context).getDvrDataManager()
+                .getSeriesRecording(seriesRecordingId);
+        if (series == null) {
+            return;
+        }
+        if (programs != null) {
+            startSeriesSettingsActivityInternal(context, seriesRecordingId, programs,
+                    removeEmptySeriesSchedule, isWindowTranslucent,
+                    showViewScheduleOptionInDialog, currentProgram);
+        } else {
+            EpisodicProgramLoadTask episodicProgramLoadTask =
+                    new EpisodicProgramLoadTask(context, series) {
+                @Override
+                protected void onPostExecute(List<Program> loadedPrograms) {
+                    sProgressDialog.dismiss();
+                    sProgressDialog = null;
+                    startSeriesSettingsActivityInternal(context, seriesRecordingId,
+                            loadedPrograms == null ? Collections.EMPTY_LIST : loadedPrograms,
+                            removeEmptySeriesSchedule, isWindowTranslucent,
+                            showViewScheduleOptionInDialog, currentProgram);
+                }
+            }.setLoadCurrentProgram(true)
+                    .setLoadDisallowedProgram(true)
+                    .setLoadScheduledEpisode(true)
+                    .setIgnoreChannelOption(true);
+            sProgressDialog = ProgressDialog.show(context, null, context.getString(
+                    R.string.dvr_series_progress_message_reading_programs), true, true,
+                    new DialogInterface.OnCancelListener() {
+                        @Override
+                        public void onCancel(DialogInterface dialogInterface) {
+                            episodicProgramLoadTask.cancel(true);
+                            sProgressDialog = null;
+                        }
+                    });
+            episodicProgramLoadTask.execute();
+        }
+    }
+
+    private static void startSeriesSettingsActivityInternal(Context context, long seriesRecordingId,
+            @NonNull List<Program> programs, boolean removeEmptySeriesSchedule,
+            boolean isWindowTranslucent, boolean showViewScheduleOptionInDialog,
+            Program currentProgram) {
+        SoftPreconditions.checkState(programs != null,
+                TAG, "Start series settings activity but programs is null");
+        Intent intent = new Intent(context, DvrSeriesSettingsActivity.class);
+        intent.putExtra(DvrSeriesSettingsActivity.SERIES_RECORDING_ID, seriesRecordingId);
+        BigArguments.reset();
+        BigArguments.setArgument(DvrSeriesSettingsActivity.PROGRAM_LIST, programs);
+        intent.putExtra(DvrSeriesSettingsActivity.REMOVE_EMPTY_SERIES_RECORDING,
+                removeEmptySeriesSchedule);
+        intent.putExtra(DvrSeriesSettingsActivity.IS_WINDOW_TRANSLUCENT, isWindowTranslucent);
+        intent.putExtra(DvrSeriesSettingsActivity.SHOW_VIEW_SCHEDULE_OPTION_IN_DIALOG,
+                showViewScheduleOptionInDialog);
+        intent.putExtra(DvrSeriesSettingsActivity.CURRENT_PROGRAM, currentProgram);
+        context.startActivity(intent);
+    }
+
+    /**
+     * Shows "series recording scheduled" dialog activity.
+     */
+    public static void StartSeriesScheduledDialogActivity(Context context,
+            SeriesRecording seriesRecording, boolean showViewScheduleOptionInDialog,
+            List<Program> programs) {
+        if (seriesRecording == null) {
+            return;
+        }
+        Intent intent = new Intent(context, DvrSeriesScheduledDialogActivity.class);
+        intent.putExtra(DvrSeriesScheduledDialogActivity.SERIES_RECORDING_ID,
+                seriesRecording.getId());
+        intent.putExtra(DvrSeriesScheduledDialogActivity.SHOW_VIEW_SCHEDULE_OPTION,
+                showViewScheduleOptionInDialog);
+        BigArguments.reset();
+        BigArguments.setArgument(DvrSeriesScheduledFragment.SERIES_SCHEDULED_KEY_PROGRAMS,
+                programs);
+        context.startActivity(intent);
+    }
+
+    /**
+     * Shows the details activity for the DVR items. The type of DVR items may be
+     * {@link ScheduledRecording}, {@link RecordedProgram}, or {@link SeriesRecording}.
+     */
+    public static void startDetailsActivity(Activity activity, Object dvrItem,
+            @Nullable ImageView imageView, boolean hideViewSchedule) {
+        if (dvrItem == null) {
+            return;
+        }
+        Intent intent = new Intent(activity, DvrDetailsActivity.class);
+        long recordingId;
+        int viewType;
+        if (dvrItem instanceof ScheduledRecording) {
+            ScheduledRecording schedule = (ScheduledRecording) dvrItem;
+            recordingId = schedule.getId();
+            if (schedule.getState() == ScheduledRecording.STATE_RECORDING_NOT_STARTED) {
+                viewType = DvrDetailsActivity.SCHEDULED_RECORDING_VIEW;
+            } else if (schedule.getState() == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
+                viewType = DvrDetailsActivity.CURRENT_RECORDING_VIEW;
+            } else {
+                return;
+            }
+        } else if (dvrItem instanceof RecordedProgram) {
+            recordingId = ((RecordedProgram) dvrItem).getId();
+            viewType = DvrDetailsActivity.RECORDED_PROGRAM_VIEW;
+        } else if (dvrItem instanceof SeriesRecording) {
+            recordingId = ((SeriesRecording) dvrItem).getId();
+            viewType = DvrDetailsActivity.SERIES_RECORDING_VIEW;
+        } else {
+            return;
+        }
+        intent.putExtra(DvrDetailsActivity.RECORDING_ID, recordingId);
+        intent.putExtra(DvrDetailsActivity.DETAILS_VIEW_TYPE, viewType);
+        intent.putExtra(DvrDetailsActivity.HIDE_VIEW_SCHEDULE, hideViewSchedule);
+        Bundle bundle = null;
+        if (imageView != null) {
+            bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, imageView,
+                    DvrDetailsActivity.SHARED_ELEMENT_NAME).toBundle();
+        }
+        activity.startActivity(intent, bundle);
+    }
+
+    /**
+     * Shows the cancel all dialog for series schedules list.
+     */
+    public static void showCancelAllSeriesRecordingDialog(DvrSchedulesActivity activity,
+            SeriesRecording seriesRecording) {
+        DvrStopSeriesRecordingDialogFragment dvrStopSeriesRecordingDialogFragment =
+                new DvrStopSeriesRecordingDialogFragment();
+        Bundle arguments = new Bundle();
+        arguments.putParcelable(DvrStopSeriesRecordingFragment.KEY_SERIES_RECORDING,
+                seriesRecording);
+        dvrStopSeriesRecordingDialogFragment.setArguments(arguments);
+        dvrStopSeriesRecordingDialogFragment.show(activity.getFragmentManager(),
+                DvrStopSeriesRecordingDialogFragment.DIALOG_TAG);
+    }
+
+    /**
+     * Shows the series deletion activity.
+     */
+    public static void startSeriesDeletionActivity(Context context, long seriesRecordingId) {
+        Intent intent = new Intent(context, DvrSeriesDeletionActivity.class);
+        intent.putExtra(DvrSeriesDeletionActivity.SERIES_RECORDING_ID, seriesRecordingId);
+        context.startActivity(intent);
+    }
+
+    public static void showAddScheduleToast(Context context,
+            String title, long startTimeMs, long endTimeMs) {
+        String msg = (startTimeMs > System.currentTimeMillis()) ?
+            context.getString(R.string.dvr_msg_program_scheduled, title)
+            : context.getString(R.string.dvr_msg_current_program_scheduled, title,
+                    Utils.toTimeString(endTimeMs, false));
+        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
+    }
+
+    /**
+     * Returns the styled schedule's title with its season and episode number.
+     */
+    public static CharSequence getStyledTitleWithEpisodeNumber(Context context,
+            ScheduledRecording schedule, int episodeNumberStyleResId) {
+        return getStyledTitleWithEpisodeNumber(context, schedule.getProgramTitle(),
+                schedule.getSeasonNumber(), schedule.getEpisodeNumber(), episodeNumberStyleResId);
+    }
+
+    /**
+     * Returns the styled program's title with its season and episode number.
+     */
+    public static CharSequence getStyledTitleWithEpisodeNumber(Context context,
+            BaseProgram program, int episodeNumberStyleResId) {
+        return getStyledTitleWithEpisodeNumber(context, program.getTitle(),
+                program.getSeasonNumber(), program.getEpisodeNumber(), episodeNumberStyleResId);
+    }
+
+    @NonNull
+    public static CharSequence getStyledTitleWithEpisodeNumber(Context context, String title,
+            String seasonNumber, String episodeNumber, int episodeNumberStyleResId) {
+        if (TextUtils.isEmpty(title)) {
+            return "";
+        }
+        SpannableStringBuilder builder;
+        if (TextUtils.isEmpty(seasonNumber) || seasonNumber.equals("0")) {
+            builder = TextUtils.isEmpty(episodeNumber) ? new SpannableStringBuilder(title) :
+                    new SpannableStringBuilder(Html.fromHtml(
+                            context.getString(R.string.program_title_with_episode_number_no_season,
+                                    title, episodeNumber)));
+        } else {
+            builder = new SpannableStringBuilder(Html.fromHtml(
+                    context.getString(R.string.program_title_with_episode_number,
+                            title, seasonNumber, episodeNumber)));
+        }
+        Object[] spans = builder.getSpans(0, builder.length(), Object.class);
+        if (spans.length > 0) {
+            if (episodeNumberStyleResId != 0) {
+                builder.setSpan(new TextAppearanceSpan(context, episodeNumberStyleResId),
+                        builder.getSpanStart(spans[0]), builder.getSpanEnd(spans[0]),
+                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+            }
+            builder.removeSpan(spans[0]);
+        }
+        return new SpannableString(builder);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/FadeBackground.java b/src/com/android/tv/dvr/ui/FadeBackground.java
new file mode 100644
index 0000000..4f06ebc
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/FadeBackground.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.transition.Transition;
+import android.transition.TransitionValues;
+import android.transition.Visibility;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+
+import com.android.tv.R;
+
+/**
+ * This transition fades in/out of the background of the view by changing the background color.
+ */
+public class FadeBackground extends Transition {
+    private final int mMode;
+
+    public FadeBackground(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.FadeBackground);
+        mMode = a.getInt(R.styleable.FadeBackground_fadingMode, Visibility.MODE_IN);
+        a.recycle();
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) { }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) { }
+
+    @Override
+    public Animator createAnimator(ViewGroup sceneRoot, TransitionValues startValues,
+            TransitionValues endValues) {
+        if (startValues == null || endValues == null) {
+            return null;
+        }
+        Drawable background = endValues.view.getBackground();
+        if (background instanceof ColorDrawable) {
+            int color = ((ColorDrawable) background).getColor();
+            int transparentColor = Color.argb(0, Color.red(color), Color.green(color),
+                    Color.blue(color));
+            return mMode == Visibility.MODE_OUT
+                    ? ObjectAnimator.ofArgb(background, "color", transparentColor)
+                    : ObjectAnimator.ofArgb(background, "color", transparentColor, color);
+        }
+        return null;
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/FullSchedulesCardPresenter.java b/src/com/android/tv/dvr/ui/FullSchedulesCardPresenter.java
deleted file mode 100644
index 7dd85f4..0000000
--- a/src/com/android/tv/dvr/ui/FullSchedulesCardPresenter.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.content.Context;
-import android.support.v17.leanback.widget.Presenter;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.util.Utils;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Presents a {@link ScheduledRecording} in the {@link DvrBrowseFragment}.
- */
-public class FullSchedulesCardPresenter extends Presenter {
-    @Override
-    public ViewHolder onCreateViewHolder(ViewGroup parent) {
-        Context context = parent.getContext();
-        RecordingCardView view = new RecordingCardView(context);
-        return new ScheduledRecordingViewHolder(view);
-    }
-
-    @Override
-    public void onBindViewHolder(ViewHolder baseHolder, Object o) {
-        final ScheduledRecordingViewHolder viewHolder = (ScheduledRecordingViewHolder) baseHolder;
-        final RecordingCardView cardView = (RecordingCardView) viewHolder.view;
-        final Context context = viewHolder.view.getContext();
-
-        cardView.setImage(context.getDrawable(R.drawable.dvr_full_schedule));
-        cardView.setTitle(context.getString(R.string.dvr_full_schedule_card_view_title));
-        List<ScheduledRecording> scheduledRecordings = TvApplication.getSingletons(context)
-                .getDvrDataManager().getAvailableScheduledRecordings();
-        int fullDays = 0;
-        if (!scheduledRecordings.isEmpty()) {
-            fullDays = Utils.computeDateDifference(System.currentTimeMillis(),
-                    Collections.max(scheduledRecordings, ScheduledRecording.START_TIME_COMPARATOR)
-                    .getStartTimeMs()) + 1;
-        }
-        cardView.setContent(context.getResources().getQuantityString(
-                R.plurals.dvr_full_schedule_card_view_content, fullDays, fullDays), null);
-
-        View.OnClickListener clickListener = new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                DvrUiHelper.startSchedulesActivity(context, null);
-            }
-        };
-        baseHolder.view.setOnClickListener(clickListener);
-    }
-
-    @Override
-    public void onUnbindViewHolder(ViewHolder baseHolder) {
-        ScheduledRecordingViewHolder viewHolder = (ScheduledRecordingViewHolder) baseHolder;
-        final RecordingCardView cardView = (RecordingCardView) viewHolder.view;
-        cardView.reset();
-    }
-
-    private static final class ScheduledRecordingViewHolder extends ViewHolder {
-        ScheduledRecordingViewHolder(RecordingCardView view) {
-            super(view);
-        }
-    }
-}
diff --git a/src/com/android/tv/dvr/ui/RecordedProgramPresenter.java b/src/com/android/tv/dvr/ui/RecordedProgramPresenter.java
deleted file mode 100644
index 1bf3431..0000000
--- a/src/com/android/tv/dvr/ui/RecordedProgramPresenter.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.media.tv.TvContract;
-import android.media.tv.TvInputManager;
-import android.net.Uri;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.TextUtils;
-import android.text.style.TextAppearanceSpan;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.dvr.RecordedProgram;
-import com.android.tv.data.Channel;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.dvr.DvrWatchedPositionManager;
-import com.android.tv.dvr.DvrWatchedPositionManager.WatchedPositionChangedListener;
-import com.android.tv.util.Utils;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Presents a {@link RecordedProgram} in the {@link DvrBrowseFragment}.
- */
-public class RecordedProgramPresenter extends DvrItemPresenter {
-    private final ChannelDataManager mChannelDataManager;
-    private final DvrWatchedPositionManager mDvrWatchedPositionManager;
-    private final Context mContext;
-    private String mTodayString;
-    private String mYesterdayString;
-    private final int mProgressBarColor;
-    private final boolean mShowEpisodeTitle;
-
-    private static final class RecordedProgramViewHolder extends ViewHolder
-            implements WatchedPositionChangedListener {
-        private RecordedProgram mProgram;
-
-        RecordedProgramViewHolder(RecordingCardView view, int progressColor) {
-            super(view);
-            view.setProgressBarColor(progressColor);
-        }
-
-        private void setProgram(RecordedProgram program) {
-            mProgram = program;
-        }
-
-        private void setProgressBar(long watchedPositionMs) {
-            ((RecordingCardView) view).setProgressBar(
-                    (watchedPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME) ? null
-                            : Math.min(100, (int) (100.0f * watchedPositionMs
-                                    / mProgram.getDurationMillis())));
-        }
-
-        @Override
-        public void onWatchedPositionChanged(long programId, long positionMs) {
-            if (programId == mProgram.getId()) {
-                setProgressBar(positionMs);
-            }
-        }
-    }
-
-    public RecordedProgramPresenter(Context context, boolean showEpisodeTitle) {
-        mContext = context;
-        mChannelDataManager = TvApplication.getSingletons(context).getChannelDataManager();
-        mTodayString = context.getString(R.string.dvr_date_today);
-        mYesterdayString = context.getString(R.string.dvr_date_yesterday);
-        mDvrWatchedPositionManager =
-                TvApplication.getSingletons(context).getDvrWatchedPositionManager();
-        mProgressBarColor = context.getResources()
-                .getColor(R.color.play_controls_progress_bar_watched);
-        mShowEpisodeTitle = showEpisodeTitle;
-    }
-
-    public RecordedProgramPresenter(Context context) {
-        this(context, false);
-    }
-
-    @Override
-    public ViewHolder onCreateViewHolder(ViewGroup parent) {
-        RecordingCardView view = new RecordingCardView(mContext);
-        return new RecordedProgramViewHolder(view, mProgressBarColor);
-    }
-
-    @Override
-    public void onBindViewHolder(ViewHolder viewHolder, Object o) {
-        final RecordedProgram program = (RecordedProgram) o;
-        final RecordingCardView cardView = (RecordingCardView) viewHolder.view;
-        Channel channel = mChannelDataManager.getChannel(program.getChannelId());
-        String titleString = mShowEpisodeTitle ? program.getEpisodeDisplayTitle(mContext)
-                : program.getTitleWithEpisodeNumber(mContext);
-        SpannableString title = titleString == null ? null : new SpannableString(titleString);
-        if (TextUtils.isEmpty(title)) {
-            title = new SpannableString(channel != null ? channel.getDisplayName()
-                    : mContext.getResources().getString(R.string.no_program_information));
-        } else if (!mShowEpisodeTitle) {
-            // TODO: Some translation may add delimiters in-between program titles, we should use
-            // a more robust way to get the span range.
-            String programTitle = program.getTitle();
-            title.setSpan(new TextAppearanceSpan(mContext,
-                    R.style.text_appearance_card_view_episode_number), programTitle == null ? 0
-                    : programTitle.length(), title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-        }
-        cardView.setTitle(title);
-        String imageUri = null;
-        boolean isChannelLogo = false;
-        if (program.getPosterArtUri() != null) {
-            imageUri = program.getPosterArtUri();
-        } else if (program.getThumbnailUri() != null) {
-            imageUri = program.getThumbnailUri();
-        } else if (channel != null) {
-            imageUri = TvContract.buildChannelLogoUri(channel.getId()).toString();
-            isChannelLogo = true;
-        }
-        cardView.setImageUri(imageUri, isChannelLogo);
-        int durationMinutes =
-                Math.max(1, (int) TimeUnit.MILLISECONDS.toMinutes(program.getDurationMillis()));
-        String durationString = getContext().getResources().getQuantityString(
-                R.plurals.dvr_program_duration, durationMinutes, durationMinutes);
-        cardView.setContent(getDescription(program), durationString);
-        if (viewHolder instanceof RecordedProgramViewHolder) {
-            RecordedProgramViewHolder cardViewHolder = (RecordedProgramViewHolder) viewHolder;
-            cardViewHolder.setProgram(program);
-            mDvrWatchedPositionManager.addListener(cardViewHolder, program.getId());
-            cardViewHolder
-                    .setProgressBar(mDvrWatchedPositionManager.getWatchedPosition(program.getId()));
-        }
-        super.onBindViewHolder(viewHolder, o);
-    }
-
-    @Override
-    public void onUnbindViewHolder(ViewHolder viewHolder) {
-        if (viewHolder instanceof RecordedProgramViewHolder) {
-            mDvrWatchedPositionManager.removeListener((RecordedProgramViewHolder) viewHolder,
-                    ((RecordedProgramViewHolder) viewHolder).mProgram.getId());
-        }
-        ((RecordingCardView) viewHolder.view).reset();
-        super.onUnbindViewHolder(viewHolder);
-    }
-
-    /**
-     * Returns description would be used in its card view.
-     */
-    protected String getDescription(RecordedProgram recording) {
-        int dateDifference = Utils.computeDateDifference(recording.getStartTimeUtcMillis(),
-                System.currentTimeMillis());
-        if (dateDifference == 0) {
-            return mTodayString;
-        } else if (dateDifference == 1) {
-            return mYesterdayString;
-        } else {
-            return Utils.getDurationString(mContext, recording.getStartTimeUtcMillis(),
-                    recording.getStartTimeUtcMillis(), false, true, false, 0);
-        }
-    }
-
-    /**
-     * Returns context.
-     */
-    protected Context getContext() {
-        return mContext;
-    }
-}
diff --git a/src/com/android/tv/dvr/ui/RecordingCardView.java b/src/com/android/tv/dvr/ui/RecordingCardView.java
deleted file mode 100644
index 51c3b03..0000000
--- a/src/com/android/tv/dvr/ui/RecordingCardView.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.support.annotation.Nullable;
-import android.support.v17.leanback.widget.BaseCardView;
-import android.text.TextUtils;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-
-import com.android.tv.R;
-import com.android.tv.dvr.RecordedProgram;
-import com.android.tv.util.ImageLoader;
-
-/**
- * A CardView for displaying info about a {@link com.android.tv.dvr.ScheduledRecording} or
- * {@link RecordedProgram} or
- * {@link com.android.tv.dvr.SeriesRecording}.
- */
-class RecordingCardView extends BaseCardView {
-    private final ImageView mImageView;
-    private final int mImageWidth;
-    private final int mImageHeight;
-    private String mImageUri;
-    private final TextView mTitleView;
-    private final TextView mMajorContentView;
-    private final TextView mMinorContentView;
-    private final ProgressBar mProgressBar;
-    private final View mAffiliatedIconContainer;
-    private final ImageView mAffiliatedIcon;
-    private final Drawable mDefaultImage;
-
-    RecordingCardView(Context context) {
-        this(context,
-                context.getResources().getDimensionPixelSize(R.dimen.dvr_card_image_layout_width),
-                context.getResources().getDimensionPixelSize(R.dimen.dvr_card_image_layout_height));
-    }
-
-    RecordingCardView(Context context, int imageWidth, int imageHeight) {
-        super(context);
-        //TODO(dvr): move these to the layout XML.
-        setCardType(BaseCardView.CARD_TYPE_INFO_UNDER_WITH_EXTRA);
-        setInfoVisibility(BaseCardView.CARD_REGION_VISIBLE_ALWAYS);
-        setFocusable(true);
-        setFocusableInTouchMode(true);
-        mDefaultImage = getResources().getDrawable(R.drawable.dvr_default_poster, null);
-
-        LayoutInflater inflater = LayoutInflater.from(getContext());
-        inflater.inflate(R.layout.dvr_recording_card_view, this);
-        mImageView = (ImageView) findViewById(R.id.image);
-        mImageWidth = imageWidth;
-        mImageHeight = imageHeight;
-        mProgressBar = (ProgressBar) findViewById(R.id.recording_progress);
-        mAffiliatedIconContainer = findViewById(R.id.affiliated_icon_container);
-        mAffiliatedIcon = (ImageView) findViewById(R.id.affiliated_icon);
-        mTitleView = (TextView) findViewById(R.id.title);
-        mMajorContentView = (TextView) findViewById(R.id.content_major);
-        mMinorContentView = (TextView) findViewById(R.id.content_minor);
-    }
-
-    void setTitle(CharSequence title) {
-        mTitleView.setText(title);
-    }
-
-    void setContent(CharSequence majorContent, CharSequence minorContent) {
-        if (!TextUtils.isEmpty(majorContent)) {
-            mMajorContentView.setText(majorContent);
-            mMajorContentView.setVisibility(View.VISIBLE);
-        } else {
-            mMajorContentView.setVisibility(View.GONE);
-        }
-        if (!TextUtils.isEmpty(minorContent)) {
-            mMinorContentView.setText(minorContent);
-            mMinorContentView.setVisibility(View.VISIBLE);
-        } else {
-            mMinorContentView.setVisibility(View.GONE);
-        }
-    }
-
-    /**
-     * Sets progress bar. If progress is {@code null}, hides progress bar.
-     */
-    void setProgressBar(Integer progress) {
-        if (progress == null) {
-            mProgressBar.setVisibility(View.GONE);
-        } else {
-            mProgressBar.setProgress(progress);
-            mProgressBar.setVisibility(View.VISIBLE);
-        }
-    }
-
-    /**
-     * Sets the color of progress bar.
-     */
-    void setProgressBarColor(int color) {
-        mProgressBar.getProgressDrawable().setTint(color);
-    }
-
-    void setImageUri(String uri, boolean isChannelLogo) {
-        if (isChannelLogo) {
-            mImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-        } else {
-            mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
-        }
-        mImageUri = uri;
-        if (TextUtils.isEmpty(uri)) {
-            mImageView.setImageDrawable(mDefaultImage);
-        } else {
-            ImageLoader.loadBitmap(getContext(), uri, mImageWidth, mImageHeight,
-                    new RecordingCardImageLoaderCallback(this, uri));
-        }
-    }
-
-    /**
-     * Set image to card view.
-     */
-    public void setImage(Drawable image) {
-        if (image != null) {
-            mImageView.setImageDrawable(image);
-        }
-    }
-
-    public void setAffiliatedIcon(int imageResId) {
-        if (imageResId > 0) {
-            mAffiliatedIconContainer.setVisibility(View.VISIBLE);
-            mAffiliatedIcon.setImageResource(imageResId);
-        } else {
-            mAffiliatedIconContainer.setVisibility(View.INVISIBLE);
-        }
-    }
-
-    /**
-     * Returns image view.
-     */
-    public ImageView getImageView() {
-        return mImageView;
-    }
-
-    private static class RecordingCardImageLoaderCallback
-            extends ImageLoader.ImageLoaderCallback<RecordingCardView> {
-        private final String mUri;
-
-        RecordingCardImageLoaderCallback(RecordingCardView referent, String uri) {
-            super(referent);
-            mUri = uri;
-        }
-
-        @Override
-        public void onBitmapLoaded(RecordingCardView view, @Nullable Bitmap bitmap) {
-            if (bitmap == null || !mUri.equals(view.mImageUri)) {
-                view.mImageView.setImageDrawable(view.mDefaultImage);
-            } else {
-                view.mImageView.setImageDrawable(new BitmapDrawable(view.getResources(), bitmap));
-            }
-        }
-    }
-
-    public void reset() {
-        mTitleView.setText(null);
-        setContent(null, null);
-        mImageView.setImageDrawable(mDefaultImage);
-    }
-}
diff --git a/src/com/android/tv/dvr/ui/RecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/RecordingDetailsFragment.java
deleted file mode 100644
index 4e19ec3..0000000
--- a/src/com/android/tv/dvr/ui/RecordingDetailsFragment.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.os.Bundle;
-import android.support.v17.leanback.app.DetailsFragment;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.TextUtils;
-import android.text.style.TextAppearanceSpan;
-
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.data.Channel;
-import com.android.tv.dvr.ScheduledRecording;
-
-/**
- * {@link DetailsFragment} for recordings in DVR.
- */
-abstract class RecordingDetailsFragment extends DvrDetailsFragment {
-    private ScheduledRecording mRecording;
-
-    @Override
-    protected void onCreateInternal() {
-        setDetailsOverviewRow(createDetailsContent());
-    }
-
-    @Override
-    protected boolean onLoadRecordingDetails(Bundle args) {
-        long scheduledRecordingId = args.getLong(DvrDetailsActivity.RECORDING_ID);
-        mRecording = TvApplication.getSingletons(getContext()).getDvrDataManager()
-                .getScheduledRecording(scheduledRecordingId);
-        return mRecording != null;
-    }
-
-    /**
-     * Returns {@link ScheduledRecording} for the current fragment.
-     */
-    public ScheduledRecording getRecording() {
-        return mRecording;
-    }
-
-    private DetailsContent createDetailsContent() {
-        Channel channel = TvApplication.getSingletons(getContext()).getChannelDataManager()
-                .getChannel(mRecording.getChannelId());
-        SpannableString title = mRecording.getProgramTitleWithEpisodeNumber(getContext()) == null ?
-                null : new SpannableString(mRecording
-                .getProgramTitleWithEpisodeNumber(getContext()));
-        if (TextUtils.isEmpty(title)) {
-            title = new SpannableString(channel != null ? channel.getDisplayName()
-                    : getContext().getResources().getString(
-                    R.string.no_program_information));
-        } else {
-            String programTitle = mRecording.getProgramTitle();
-            title.setSpan(new TextAppearanceSpan(getContext(),
-                    R.style.text_appearance_card_view_episode_number), programTitle == null ? 0
-                    : programTitle.length(), title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-        }
-        String description = !TextUtils.isEmpty(mRecording.getProgramDescription()) ?
-                mRecording.getProgramDescription() :  mRecording.getProgramLongDescription();
-        if (TextUtils.isEmpty(description)) {
-            description = channel != null ? channel.getDescription() : null;
-        }
-        return new DetailsContent.Builder()
-                .setTitle(title)
-                .setStartTimeUtcMillis(mRecording.getStartTimeMs())
-                .setEndTimeUtcMillis(mRecording.getEndTimeMs())
-                .setDescription(description)
-                .setImageUris(mRecording.getProgramPosterArtUri(),
-                        mRecording.getProgramThumbnailUri(), channel)
-                .build();
-    }
-}
diff --git a/src/com/android/tv/dvr/ui/ScheduledRecordingPresenter.java b/src/com/android/tv/dvr/ui/ScheduledRecordingPresenter.java
deleted file mode 100644
index 5f447f1..0000000
--- a/src/com/android/tv/dvr/ui/ScheduledRecordingPresenter.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr.ui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.media.tv.TvContract;
-import android.os.Handler;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.TextUtils;
-import android.text.style.TextAppearanceSpan;
-import android.view.ViewGroup;
-
-import com.android.tv.ApplicationSingletons;
-import com.android.tv.R;
-import com.android.tv.TvApplication;
-import com.android.tv.data.Channel;
-import com.android.tv.data.ChannelDataManager;
-import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.util.Utils;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Presents a {@link ScheduledRecording} in the {@link DvrBrowseFragment}.
- */
-public class ScheduledRecordingPresenter extends DvrItemPresenter {
-    private static final long PROGRESS_UPDATE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(5);
-
-    private final ChannelDataManager mChannelDataManager;
-    private final DvrManager mDvrManager;
-    private final Context mContext;
-    private final int mProgressBarColor;
-
-    private static final class ScheduledRecordingViewHolder extends ViewHolder {
-        private final Handler mHandler = new Handler();
-        private ScheduledRecording mScheduledRecording;
-        private final Runnable mProgressBarUpdater = new Runnable() {
-            @Override
-            public void run() {
-                updateProgressBar();
-                mHandler.postDelayed(this, PROGRESS_UPDATE_INTERVAL_MS);
-            }
-        };
-
-        ScheduledRecordingViewHolder(RecordingCardView view, int progressBarColor) {
-            super(view);
-            view.setProgressBarColor(progressBarColor);
-        }
-
-        private void updateProgressBar() {
-            if (mScheduledRecording == null) {
-                return;
-            }
-            int recordingState = mScheduledRecording.getState();
-            RecordingCardView cardView = (RecordingCardView) view;
-            if (recordingState == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
-                cardView.setProgressBar(Math.max(0, Math.min((int) (100 *
-                        (System.currentTimeMillis() - mScheduledRecording.getStartTimeMs())
-                        / mScheduledRecording.getDuration()), 100)));
-            } else if (recordingState == ScheduledRecording.STATE_RECORDING_FINISHED) {
-                cardView.setProgressBar(100);
-            } else {
-                // Hides progress bar.
-                cardView.setProgressBar(null);
-            }
-        }
-
-        private void startUpdateProgressBar() {
-            mHandler.post(mProgressBarUpdater);
-        }
-
-        private void stopUpdateProgressBar() {
-            mHandler.removeCallbacks(mProgressBarUpdater);
-        }
-    }
-
-    public ScheduledRecordingPresenter(Context context) {
-        ApplicationSingletons singletons = TvApplication.getSingletons(context);
-        mChannelDataManager = singletons.getChannelDataManager();
-        mDvrManager = singletons.getDvrManager();
-        mContext = context;
-        mProgressBarColor = context.getResources()
-                .getColor(R.color.play_controls_recording_icon_color_on_focus);
-    }
-
-    @Override
-    public ViewHolder onCreateViewHolder(ViewGroup parent) {
-        Context context = parent.getContext();
-        RecordingCardView view = new RecordingCardView(context);
-        return new ScheduledRecordingViewHolder(view, mProgressBarColor);
-    }
-
-    @Override
-    public void onBindViewHolder(ViewHolder baseHolder, Object o) {
-        final ScheduledRecordingViewHolder viewHolder = (ScheduledRecordingViewHolder) baseHolder;
-        final ScheduledRecording recording = (ScheduledRecording) o;
-        final RecordingCardView cardView = (RecordingCardView) viewHolder.view;
-        final Context context = viewHolder.view.getContext();
-
-        setTitleAndImage(cardView, recording);
-        int dateDifference = Utils.computeDateDifference(System.currentTimeMillis(),
-                recording.getStartTimeMs());
-        if (dateDifference <= 0) {
-            cardView.setContent(mContext.getString(R.string.dvr_date_today_time,
-                    Utils.getDurationString(context, recording.getStartTimeMs(),
-                            recording.getEndTimeMs(), false, false, true, 0)), null);
-        } else if (dateDifference == 1) {
-            cardView.setContent(mContext.getString(R.string.dvr_date_tomorrow_time,
-                    Utils.getDurationString(context, recording.getStartTimeMs(),
-                            recording.getEndTimeMs(), false, false, true, 0)), null);
-        } else {
-            cardView.setContent(Utils.getDurationString(context, recording.getStartTimeMs(),
-                    recording.getStartTimeMs(), false, true, false, 0), null);
-        }
-        if (mDvrManager.isConflicting(recording)) {
-            cardView.setAffiliatedIcon(R.drawable.ic_warning_white_32dp);
-        } else {
-            cardView.setAffiliatedIcon(0);
-        }
-        viewHolder.updateProgressBar();
-        viewHolder.mScheduledRecording = recording;
-        viewHolder.startUpdateProgressBar();
-        super.onBindViewHolder(viewHolder, o);
-    }
-
-    @Override
-    public void onUnbindViewHolder(ViewHolder baseHolder) {
-        ScheduledRecordingViewHolder viewHolder = (ScheduledRecordingViewHolder) baseHolder;
-        viewHolder.stopUpdateProgressBar();
-        final RecordingCardView cardView = (RecordingCardView) viewHolder.view;
-        viewHolder.mScheduledRecording = null;
-        cardView.reset();
-        super.onUnbindViewHolder(viewHolder);
-    }
-
-    private void setTitleAndImage(RecordingCardView cardView, ScheduledRecording recording) {
-        Channel channel = mChannelDataManager.getChannel(recording.getChannelId());
-        SpannableString title = recording.getProgramTitleWithEpisodeNumber(mContext) == null ?
-                null : new SpannableString(recording.getProgramTitleWithEpisodeNumber(mContext));
-        if (TextUtils.isEmpty(title)) {
-            title = new SpannableString(channel != null ? channel.getDisplayName()
-                    : mContext.getResources().getString(R.string.no_program_information));
-        } else {
-            String programTitle = recording.getProgramTitle();
-            title.setSpan(new TextAppearanceSpan(mContext,
-                    R.style.text_appearance_card_view_episode_number),
-                    programTitle == null ? 0 : programTitle.length(), title.length(),
-                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-        }
-        String imageUri = recording.getProgramPosterArtUri();
-        boolean isChannelLogo = false;
-        if (TextUtils.isEmpty(imageUri)) {
-            imageUri = channel != null ?
-                    TvContract.buildChannelLogoUri(channel.getId()).toString() : null;
-            isChannelLogo = true;
-        }
-        cardView.setTitle(title);
-        cardView.setImageUri(imageUri, isChannelLogo);
-    }
-}
diff --git a/src/com/android/tv/dvr/ui/SortedArrayAdapter.java b/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
index 393a5ff..8c0af9e 100644
--- a/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
+++ b/src/com/android/tv/dvr/ui/SortedArrayAdapter.java
@@ -20,11 +20,15 @@
 import android.support.v17.leanback.widget.ArrayObjectAdapter;
 import android.support.v17.leanback.widget.PresenterSelector;
 
+import com.android.tv.common.SoftPreconditions;
+
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Keeps a set of items sorted
@@ -35,16 +39,18 @@
     private final Comparator<T> mComparator;
     private final int mMaxItemCount;
     private int mExtraItemCount;
+    private final Set<Long> mIds = new HashSet<>();
 
-    SortedArrayAdapter(PresenterSelector presenterSelector, Comparator<T> comparator) {
+    public SortedArrayAdapter(PresenterSelector presenterSelector, Comparator<T> comparator) {
         this(presenterSelector, comparator, Integer.MAX_VALUE);
     }
 
-    SortedArrayAdapter(PresenterSelector presenterSelector, Comparator<T> comparator,
+    public SortedArrayAdapter(PresenterSelector presenterSelector, Comparator<T> comparator,
             int maxItemCount) {
         super(presenterSelector);
         mComparator = comparator;
         mMaxItemCount = maxItemCount;
+        setHasStableIds(true);
     }
 
     /**
@@ -56,7 +62,12 @@
     final void setInitialItems(List<T> items) {
         List<T> itemsCopy = new ArrayList<>(items);
         Collections.sort(itemsCopy, mComparator);
-        addAll(0, itemsCopy.subList(0, Math.min(mMaxItemCount, itemsCopy.size())));
+        for (T item : itemsCopy) {
+            add(item, true);
+            if (size() == mMaxItemCount) {
+                break;
+            }
+        }
     }
 
     /**
@@ -82,6 +93,9 @@
      *                    the end to save search time.
      */
     public final void add(T item, boolean insertToEnd) {
+        long newItemId = getId(item);
+        SoftPreconditions.checkState(!mIds.contains(newItemId));
+        mIds.add(newItemId);
         int i;
         if (insertToEnd) {
             i = findInsertPosition(item);
@@ -89,8 +103,9 @@
             i = findInsertPositionBinary(item);
         }
         super.add(i, item);
-        if (size() > mMaxItemCount + mExtraItemCount) {
-            removeItems(mMaxItemCount, size() - mMaxItemCount - mExtraItemCount);
+        if (mMaxItemCount < Integer.MAX_VALUE && size() > mMaxItemCount + mExtraItemCount) {
+            Object removedItem = get(mMaxItemCount);
+            remove(removedItem);
         }
     }
 
@@ -100,48 +115,97 @@
      * They will be presented in their insertion order.
      */
     public int addExtraItem(T item) {
+        long newItemId = getId(item);
+        SoftPreconditions.checkState(!mIds.contains(newItemId));
+        mIds.add(newItemId);
         super.add(item);
         return ++mExtraItemCount;
     }
 
+    @Override
+    public boolean remove(Object item) {
+        return removeWithId((T) item);
+    }
+
     /**
      * Removes an item which has the same ID as {@code item}.
      */
     public boolean removeWithId(T item) {
-        int index = indexWithTypeAndId(item);
-        return index >= 0 && index < size() && remove(get(index));
+        int index = indexWithId(item);
+        return index >= 0 && index < size() && removeItems(index, 1) == 1;
+    }
+
+    @Override
+    public int removeItems(int position, int count) {
+        int upperBound = Math.min(position + count, size());
+        for (int i = position; i < upperBound; i++) {
+            mIds.remove(getId((T) get(i)));
+        }
+        if (upperBound > size() - mExtraItemCount) {
+            mExtraItemCount -= upperBound - Math.max(size() - mExtraItemCount, position);
+        }
+        return super.removeItems(position, count);
+    }
+
+    @Override
+    public void replace(int position, Object item) {
+        boolean wasExtra = position >= size() - mExtraItemCount;
+        removeItems(position, 1);
+        if (!wasExtra) {
+            add(item);
+        } else {
+            addExtraItem((T) item);
+        }
+    }
+
+    @Override
+    public void clear() {
+        mIds.clear();
+        super.clear();
     }
 
     /**
-     * Change an item in the list.
+     * Changes an item in the list.
      * @param item The item to change.
      */
     public final void change(T item) {
-        int oldIndex = indexWithTypeAndId(item);
+        int oldIndex = indexWithId(item);
         if (oldIndex != -1) {
             T old = (T) get(oldIndex);
             if (mComparator.compare(old, item) == 0) {
                 replace(oldIndex, item);
                 return;
             }
-            removeItems(oldIndex, 1);
+            remove(old);
         }
         add(item);
     }
 
     /**
+     * Checks whether the item is in the list.
+     */
+    public final boolean contains(T item) {
+        return indexWithId(item) != -1;
+    }
+
+    @Override
+    public long getId(int position) {
+        return getId((T) get(position));
+    }
+
+    /**
      * Returns the id of the the given {@code item}, which will be used in {@link #change} to
      * decide if the given item is already existed in the adapter.
      *
      * The id must be stable.
      */
-    abstract long getId(T item);
+    protected abstract long getId(T item);
 
-    private int indexWithTypeAndId(T item) {
+    private int indexWithId(T item) {
         long id = getId(item);
         for (int i = 0; i < size() - mExtraItemCount; i++) {
             T r = (T) get(i);
-            if (r.getClass() == item.getClass() && getId(r) == id) {
+            if (getId(r) == id) {
                 return i;
             }
         }
diff --git a/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java b/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java
new file mode 100644
index 0000000..5fe9c47
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/TrackedGuidedStepFragment.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 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.dvr.ui;
+
+import android.content.Context;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidedAction;
+
+import com.android.tv.TvApplication;
+import com.android.tv.analytics.Tracker;
+
+/** A {@link GuidedStepFragment} with {@link Tracker} for analytics. */
+public abstract class TrackedGuidedStepFragment extends GuidedStepFragment {
+    private Tracker mTracker;
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mTracker = TvApplication.getSingletons(context).getAnalytics().getDefaultTracker();
+    }
+
+    @Override
+    public void onDetach() {
+        mTracker = null;
+        super.onDetach();
+    }
+
+    @Override
+    public final void onGuidedActionClicked(GuidedAction action) {
+        super.onGuidedActionClicked(action);
+        if (mTracker != null) {
+            mTracker.sendMenuClicked(
+                    getTrackerPrefix() + "-action-" + getTrackerLabelForGuidedAction(action));
+        }
+        onTrackedGuidedActionClicked(action);
+    }
+
+    public String getTrackerLabelForGuidedAction(GuidedAction action) {
+        long actionId = action.getId();
+        if (actionId == GuidedAction.ACTION_ID_CANCEL) {
+            return "cancel";
+        } else if (actionId == GuidedAction.ACTION_ID_NEXT) {
+            return "next";
+        } else if (actionId == GuidedAction.ACTION_ID_CURRENT) {
+            return "current";
+        } else if (actionId == GuidedAction.ACTION_ID_OK) {
+            return "ok";
+        } else if (actionId == GuidedAction.ACTION_ID_CANCEL) {
+            return "cancel";
+        } else if (actionId == GuidedAction.ACTION_ID_FINISH) {
+            return "finish";
+        } else if (actionId == GuidedAction.ACTION_ID_CONTINUE) {
+            return "continue";
+        } else if (actionId == GuidedAction.ACTION_ID_YES) {
+            return "yes";
+        } else if (actionId == GuidedAction.ACTION_ID_NO) {
+            return "no";
+        } else {
+            return "unknown-" + actionId;
+        }
+    }
+
+    /** Delegated from {@link #onGuidedActionClicked(GuidedAction)} */
+    public abstract void onTrackedGuidedActionClicked(GuidedAction action);
+
+    /** The prefix used for analytics tracking, Usually the class name. */
+    public abstract String getTrackerPrefix();
+}
diff --git a/src/com/android/tv/dvr/ui/ActionPresenterSelector.java b/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
similarity index 92%
rename from src/com/android/tv/dvr/ui/ActionPresenterSelector.java
rename to src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
index 8b8cd5c..38a78f5 100644
--- a/src/com/android/tv/dvr/ui/ActionPresenterSelector.java
+++ b/src/com/android/tv/dvr/ui/browse/ActionPresenterSelector.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.graphics.drawable.Drawable;
 import android.support.v17.leanback.R;
@@ -110,11 +110,7 @@
                         .getDimensionPixelSize(R.dimen.lb_action_padding_horizontal);
                 vh.view.setPaddingRelative(padding, 0, padding, 0);
             }
-            if (vh.mLayoutDirection == View.LAYOUT_DIRECTION_RTL) {
-                vh.mButton.setCompoundDrawablesWithIntrinsicBounds(null, null, icon, null);
-            } else {
-                vh.mButton.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
-            }
+            vh.mButton.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null);
 
             CharSequence line1 = action.getLabel1();
             CharSequence line2 = action.getLabel2();
@@ -130,7 +126,7 @@
         @Override
         public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
             ActionViewHolder vh = (ActionViewHolder) viewHolder;
-            vh.mButton.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null);
+            vh.mButton.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null);
             vh.view.setPadding(0, 0, 0, 0);
             vh.mAction = null;
         }
diff --git a/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java
new file mode 100644
index 0000000..bf18ddc
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/CurrentRecordingDetailsFragment.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.browse;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.v17.leanback.widget.Action;
+import android.support.v17.leanback.widget.OnActionClickedListener;
+import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
+
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.dialog.HalfSizedDialogFragment;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.ui.DvrStopRecordingFragment;
+import com.android.tv.dvr.ui.DvrUiHelper;
+
+/**
+ * {@link RecordingDetailsFragment} for current recording in DVR.
+ */
+public class CurrentRecordingDetailsFragment extends RecordingDetailsFragment {
+    private static final int ACTION_STOP_RECORDING = 1;
+
+    private DvrDataManager mDvrDataManger;
+    private final DvrDataManager.ScheduledRecordingListener mScheduledRecordingListener =
+            new DvrDataManager.ScheduledRecordingListener() {
+                @Override
+                public void onScheduledRecordingAdded(ScheduledRecording... schedules) { }
+
+                @Override
+                public void onScheduledRecordingRemoved(ScheduledRecording... schedules) {
+                    for (ScheduledRecording schedule : schedules) {
+                        if (schedule.getId() == getRecording().getId()) {
+                            getActivity().finish();
+                            return;
+                        }
+                    }
+                }
+
+                @Override
+                public void onScheduledRecordingStatusChanged(ScheduledRecording... schedules) {
+                    for (ScheduledRecording schedule : schedules) {
+                        if (schedule.getId() == getRecording().getId()
+                                && schedule.getState()
+                                != ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
+                            getActivity().finish();
+                            return;
+                        }
+                    }
+                }
+            };
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        mDvrDataManger = TvApplication.getSingletons(context).getDvrDataManager();
+        mDvrDataManger.addScheduledRecordingListener(mScheduledRecordingListener);
+    }
+
+    @Override
+    protected SparseArrayObjectAdapter onCreateActionsAdapter() {
+        SparseArrayObjectAdapter adapter =
+                new SparseArrayObjectAdapter(new ActionPresenterSelector());
+        Resources res = getResources();
+        adapter.set(ACTION_STOP_RECORDING, new Action(ACTION_STOP_RECORDING,
+                res.getString(R.string.dvr_detail_stop_recording), null,
+                res.getDrawable(R.drawable.lb_ic_stop)));
+        return adapter;
+    }
+
+    @Override
+    protected OnActionClickedListener onCreateOnActionClickedListener() {
+        return new OnActionClickedListener() {
+            @Override
+            public void onActionClicked(Action action) {
+                if (action.getId() == ACTION_STOP_RECORDING) {
+                    DvrUiHelper.showStopRecordingDialog(getActivity(),
+                            getRecording().getChannelId(),
+                            DvrStopRecordingFragment.REASON_USER_STOP,
+                            new HalfSizedDialogFragment.OnActionClickListener() {
+                                @Override
+                                public void onActionClick(long actionId) {
+                                    if (actionId == DvrStopRecordingFragment.ACTION_STOP) {
+                                        DvrManager dvrManager =
+                                                TvApplication.getSingletons(getContext())
+                                                        .getDvrManager();
+                                        dvrManager.stopRecording(getRecording());
+                                        getActivity().finish();
+                                    }
+                                }
+                            });
+                }
+            }
+        };
+    }
+
+    @Override
+    public void onDetach() {
+        if (mDvrDataManger != null) {
+            mDvrDataManger.removeScheduledRecordingListener(mScheduledRecordingListener);
+        }
+        super.onDetach();
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/browse/DetailsContent.java b/src/com/android/tv/dvr/ui/browse/DetailsContent.java
new file mode 100644
index 0000000..c1fa05d
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/DetailsContent.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.browse;
+
+import android.content.Context;
+import android.media.tv.TvContract;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.data.Channel;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.ui.DvrUiHelper;
+
+/**
+ * A class for details content.
+ */
+class DetailsContent {
+    /** Constant for invalid time. */
+    public static final long INVALID_TIME = -1;
+
+    private CharSequence mTitle;
+    private long mStartTimeUtcMillis;
+    private long mEndTimeUtcMillis;
+    private String mDescription;
+    private String mLogoImageUri;
+    private String mBackgroundImageUri;
+    private boolean mUsingChannelLogo;
+
+    static DetailsContent createFromRecordedProgram(Context context,
+            RecordedProgram recordedProgram) {
+        return new DetailsContent.Builder()
+                .setChannelId(recordedProgram.getChannelId())
+                .setProgramTitle(recordedProgram.getTitle())
+                .setSeasonNumber(recordedProgram.getSeasonNumber())
+                .setEpisodeNumber(recordedProgram.getEpisodeNumber())
+                .setStartTimeUtcMillis(recordedProgram.getStartTimeUtcMillis())
+                .setEndTimeUtcMillis(recordedProgram.getEndTimeUtcMillis())
+                .setDescription(TextUtils.isEmpty(recordedProgram.getLongDescription())
+                        ? recordedProgram.getDescription() : recordedProgram.getLongDescription())
+                .setPosterArtUri(recordedProgram.getPosterArtUri())
+                .setThumbnailUri(recordedProgram.getThumbnailUri())
+                .build(context);
+    }
+
+    static DetailsContent createFromSeriesRecording(Context context,
+            SeriesRecording seriesRecording) {
+        return new DetailsContent.Builder()
+                .setChannelId(seriesRecording.getChannelId())
+                .setTitle(seriesRecording.getTitle())
+                .setDescription(TextUtils.isEmpty(seriesRecording.getLongDescription())
+                        ? seriesRecording.getDescription() : seriesRecording.getLongDescription())
+                .setPosterArtUri(seriesRecording.getPosterUri())
+                .setThumbnailUri(seriesRecording.getPhotoUri())
+                .build(context);
+    }
+
+    static DetailsContent createFromScheduledRecording(Context context,
+            ScheduledRecording scheduledRecording) {
+        Channel channel = TvApplication.getSingletons(context).getChannelDataManager()
+                .getChannel(scheduledRecording.getChannelId());
+        String description = !TextUtils.isEmpty(scheduledRecording.getProgramDescription()) ?
+                scheduledRecording.getProgramDescription()
+                : scheduledRecording.getProgramLongDescription();
+        if (TextUtils.isEmpty(description)) {
+            description = channel != null ? channel.getDescription() : null;
+        }
+        return new DetailsContent.Builder()
+                .setChannelId(scheduledRecording.getChannelId())
+                .setProgramTitle(scheduledRecording.getProgramTitle())
+                .setSeasonNumber(scheduledRecording.getSeasonNumber())
+                .setEpisodeNumber(scheduledRecording.getEpisodeNumber())
+                .setStartTimeUtcMillis(scheduledRecording.getStartTimeMs())
+                .setEndTimeUtcMillis(scheduledRecording.getEndTimeMs())
+                .setDescription(description)
+                .setPosterArtUri(scheduledRecording.getProgramPosterArtUri())
+                .setThumbnailUri(scheduledRecording.getProgramThumbnailUri())
+                .build(context);
+    }
+
+    private DetailsContent() { }
+
+    /**
+     * Returns title.
+     */
+    public CharSequence getTitle() {
+        return mTitle;
+    }
+
+    /**
+     * Returns start time.
+     */
+    public long getStartTimeUtcMillis() {
+        return mStartTimeUtcMillis;
+    }
+
+    /**
+     * Returns end time.
+     */
+    public long getEndTimeUtcMillis() {
+        return mEndTimeUtcMillis;
+    }
+
+    /**
+     * Returns description.
+     */
+    public String getDescription() {
+        return mDescription;
+    }
+
+    /**
+     * Returns Logo image URI as a String.
+     */
+    public String getLogoImageUri() {
+        return mLogoImageUri;
+    }
+
+    /**
+     * Returns background image URI as a String.
+     */
+    public String getBackgroundImageUri() {
+        return mBackgroundImageUri;
+    }
+
+    /**
+     * Returns if image URIs are from its channels' logo.
+     */
+    public boolean isUsingChannelLogo() {
+        return mUsingChannelLogo;
+    }
+
+    /**
+     * Copies other details content.
+     */
+    public void copyFrom(DetailsContent other) {
+        if (this == other) {
+            return;
+        }
+        mTitle = other.mTitle;
+        mStartTimeUtcMillis = other.mStartTimeUtcMillis;
+        mEndTimeUtcMillis = other.mEndTimeUtcMillis;
+        mDescription = other.mDescription;
+        mLogoImageUri = other.mLogoImageUri;
+        mBackgroundImageUri = other.mBackgroundImageUri;
+        mUsingChannelLogo = other.mUsingChannelLogo;
+    }
+
+    /**
+     * A class for building details content.
+     */
+    public static final class Builder {
+        private final DetailsContent mDetailsContent;
+
+        private long mChannelId;
+        private String mProgramTitle;
+        private String mSeasonNumber;
+        private String mEpisodeNumber;
+        private String mPosterArtUri;
+        private String mThumbnailUri;
+
+        public Builder() {
+            mDetailsContent = new DetailsContent();
+            mDetailsContent.mStartTimeUtcMillis = INVALID_TIME;
+            mDetailsContent.mEndTimeUtcMillis = INVALID_TIME;
+        }
+
+        /**
+         * Sets title.
+         */
+        public Builder setTitle(CharSequence title) {
+            mDetailsContent.mTitle = title;
+            return this;
+        }
+
+        /**
+         * Sets start time.
+         */
+        public Builder setStartTimeUtcMillis(long startTimeUtcMillis) {
+            mDetailsContent.mStartTimeUtcMillis = startTimeUtcMillis;
+            return this;
+        }
+
+        /**
+         * Sets end time.
+         */
+        public Builder setEndTimeUtcMillis(long endTimeUtcMillis) {
+            mDetailsContent.mEndTimeUtcMillis = endTimeUtcMillis;
+            return this;
+        }
+
+        /**
+         * Sets description.
+         */
+        public Builder setDescription(String description) {
+            mDetailsContent.mDescription = description;
+            return this;
+        }
+
+        /**
+         * Sets logo image URI as a String.
+         */
+        public Builder setLogoImageUri(String logoImageUri) {
+            mDetailsContent.mLogoImageUri = logoImageUri;
+            return this;
+        }
+
+        /**
+         * Sets background image URI as a String.
+         */
+        public Builder setBackgroundImageUri(String backgroundImageUri) {
+            mDetailsContent.mBackgroundImageUri = backgroundImageUri;
+            return this;
+        }
+
+        private Builder setProgramTitle(String programTitle) {
+            mProgramTitle = programTitle;
+            return this;
+        }
+
+        private Builder setSeasonNumber(String seasonNumber) {
+            mSeasonNumber = seasonNumber;
+            return this;
+        }
+
+        private Builder setEpisodeNumber(String episodeNumber) {
+            mEpisodeNumber = episodeNumber;
+            return this;
+        }
+
+        private Builder setChannelId(long channelId) {
+            mChannelId = channelId;
+            return this;
+        }
+
+        private Builder setPosterArtUri(String posterArtUri) {
+            mPosterArtUri = posterArtUri;
+            return this;
+        }
+
+        private Builder setThumbnailUri(String thumbnailUri) {
+            mThumbnailUri = thumbnailUri;
+            return this;
+        }
+
+        private void createStyledTitle(Context context, Channel channel) {
+            CharSequence title = DvrUiHelper.getStyledTitleWithEpisodeNumber(context,
+                    mProgramTitle, mSeasonNumber, mEpisodeNumber,
+                    R.style.text_appearance_card_view_episode_number);
+            if (TextUtils.isEmpty(title)) {
+                mDetailsContent.mTitle = channel != null ? channel.getDisplayName()
+                        : context.getResources().getString(R.string.no_program_information);
+            } else {
+                mDetailsContent.mTitle = title;
+            }
+        }
+
+        private void createImageUris(@Nullable Channel channel) {
+            mDetailsContent.mLogoImageUri = null;
+            mDetailsContent.mBackgroundImageUri = null;
+            mDetailsContent.mUsingChannelLogo = false;
+            if (!TextUtils.isEmpty(mPosterArtUri) && !TextUtils.isEmpty(mThumbnailUri)) {
+                mDetailsContent.mLogoImageUri = mPosterArtUri;
+                mDetailsContent.mBackgroundImageUri = mThumbnailUri;
+            } else if (!TextUtils.isEmpty(mPosterArtUri)) {
+                // thumbnailUri is empty
+                mDetailsContent.mLogoImageUri = mPosterArtUri;
+                mDetailsContent.mBackgroundImageUri = mPosterArtUri;
+            } else if (!TextUtils.isEmpty(mThumbnailUri)) {
+                // posterArtUri is empty
+                mDetailsContent.mLogoImageUri = mThumbnailUri;
+                mDetailsContent.mBackgroundImageUri = mThumbnailUri;
+            }
+            if (TextUtils.isEmpty(mDetailsContent.mLogoImageUri) && channel != null) {
+                String channelLogoUri = TvContract.buildChannelLogoUri(channel.getId())
+                        .toString();
+                mDetailsContent.mLogoImageUri = channelLogoUri;
+                mDetailsContent.mBackgroundImageUri = channelLogoUri;
+                mDetailsContent.mUsingChannelLogo = true;
+            }
+        }
+
+        /**
+         * Builds details content.
+         */
+        public DetailsContent build(Context context) {
+            Channel channel = TvApplication.getSingletons(context).getChannelDataManager()
+                    .getChannel(mChannelId);
+            if (mDetailsContent.mTitle == null) {
+                createStyledTitle(context, channel);
+            }
+            if (mDetailsContent.mBackgroundImageUri == null
+                    && mDetailsContent.mLogoImageUri == null) {
+                createImageUris(channel);
+            }
+            DetailsContent detailsContent = new DetailsContent();
+            detailsContent.copyFrom(mDetailsContent);
+            return detailsContent;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DetailsContentPresenter.java b/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
similarity index 82%
rename from src/com/android/tv/dvr/ui/DetailsContentPresenter.java
rename to src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
index 175f05b..09b5788 100644
--- a/src/com/android/tv/dvr/ui/DetailsContentPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsContentPresenter.java
@@ -14,13 +14,14 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.app.Activity;
 import android.animation.Animator;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
+import android.content.Context;
 import android.graphics.Paint;
 import android.graphics.Paint.FontMetricsInt;
 import android.support.v17.leanback.widget.Presenter;
@@ -29,6 +30,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.accessibility.AccessibilityManager;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
@@ -38,13 +40,14 @@
 
 /**
  * An {@link Presenter} for rendering a detailed description of an DVR item.
- * Typically this Presenter will be used in a {@link DetailsOverviewRowPresenter}.
+ * Typically this Presenter will be used in a
+ * {@link android.support.v17.leanback.widget.DetailsOverviewRowPresenter}.
  * Most codes of this class is originated from
  * {@link android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter}.
  * The latter class are re-used to provide a customized version of
  * {@link android.support.v17.leanback.widget.DetailsOverviewRow}.
  */
-public class DetailsContentPresenter extends Presenter {
+class DetailsContentPresenter extends Presenter {
     /**
      * The ViewHolder for the {@link DetailsContentPresenter}.
      */
@@ -82,25 +85,38 @@
                             return false;
                         }
                         final int bodyLines = mBody.getLineCount();
-                        final int maxLines = mFullTextMode ? bodyLines :
+                        int maxLines = mFullTextMode ? bodyLines :
                                 (mTitle.getLineCount() > 1 ? mBodyMinLines : mBodyMaxLines);
                         if (bodyLines > maxLines) {
                             mReadMoreView.setVisibility(View.VISIBLE);
                             mDescriptionContainer.setFocusable(true);
+                            mDescriptionContainer.setClickable(true);
                             mDescriptionContainer.setOnClickListener(new View.OnClickListener() {
                                 @Override
                                 public void onClick(View view) {
                                     mFullTextMode = true;
                                     mReadMoreView.setVisibility(View.GONE);
-                                    mDescriptionContainer.setFocusable(false);
+                                    mDescriptionContainer.setFocusable((
+                                            (AccessibilityManager) view.getContext()
+                                                    .getSystemService(
+                                                            Context.ACCESSIBILITY_SERVICE))
+                                            .isEnabled());
+                                    mDescriptionContainer.setClickable(false);
                                     mDescriptionContainer.setOnClickListener(null);
+                                    int oldMaxLines = mBody.getMaxLines();
                                     mBody.setMaxLines(bodyLines);
                                     // Minus 1 from line difference to eliminate the space
                                     // originally occupied by "READ MORE"
-                                    showFullText((bodyLines - maxLines - 1) * mBodyLineSpacing);
+                                    showFullText((bodyLines - oldMaxLines - 1) * mBodyLineSpacing);
                                 }
                             });
                         }
+                        if (mReadMoreView.getVisibility() == View.VISIBLE
+                                && mSubtitle.getVisibility() == View.VISIBLE) {
+                            // If both "READ MORE" and subtitle is shown, the capable maximum lines
+                            // will be one line less.
+                            maxLines -= 1;
+                        }
                         if (mBody.getMaxLines() != maxLines) {
                             mBody.setMaxLines(maxLines);
                             return false;
@@ -113,11 +129,30 @@
 
         public ViewHolder(final View view) {
             super(view);
+            view.addOnAttachStateChangeListener(
+                    new View.OnAttachStateChangeListener() {
+                        @Override
+                        public void onViewAttachedToWindow(View v) {
+                            // In case predraw listener was removed in detach, make sure
+                            // we have the proper layout.
+                            addPreDrawListener();
+                        }
+
+                        @Override
+                        public void onViewDetachedFromWindow(View v) {
+                            removePreDrawListener();
+                        }
+                    });
             mTitle = (TextView) view.findViewById(R.id.dvr_details_description_title);
             mSubtitle = (TextView) view.findViewById(R.id.dvr_details_description_subtitle);
             mBody = (TextView) view.findViewById(R.id.dvr_details_description_body);
             mDescriptionContainer =
                     (LinearLayout) view.findViewById(R.id.dvr_details_description_container);
+            // We have to explicitly set focusable to true here for accessibility, since we might
+            // set the view's focusable state when we need to show "READ MORE", which would remove
+            // the default focusable state for accessibility.
+            mDescriptionContainer.setFocusable(((AccessibilityManager) view.getContext()
+                    .getSystemService(Context.ACCESSIBILITY_SERVICE)).isEnabled());
             mReadMoreView = (TextView) view.findViewById(R.id.dvr_details_description_read_more);
 
             FontMetricsInt titleFontMetricsInt = getFontMetricsInt(mTitle);
@@ -129,7 +164,7 @@
             mUnderTitleBaselineMargin = view.getResources().getDimensionPixelSize(
                     R.dimen.lb_details_description_under_title_baseline_margin);
             mUnderSubtitleBaselineMargin = view.getResources().getDimensionPixelSize(
-                    R.dimen.lb_details_description_under_subtitle_baseline_margin);
+                    R.dimen.dvr_details_description_under_subtitle_baseline_margin);
 
             mTitleLineSpacing = view.getResources().getDimensionPixelSize(
                     R.dimen.lb_details_description_title_line_spacing);
@@ -276,22 +311,6 @@
     @Override
     public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) { }
 
-    @Override
-    public void onViewAttachedToWindow(Presenter.ViewHolder holder) {
-        // In case predraw listener was removed in detach, make sure
-        // we have the proper layout.
-        ViewHolder vh = (ViewHolder) holder;
-        vh.addPreDrawListener();
-        super.onViewAttachedToWindow(holder);
-    }
-
-    @Override
-    public void onViewDetachedFromWindow(Presenter.ViewHolder holder) {
-        ViewHolder vh = (ViewHolder) holder;
-        vh.removePreDrawListener();
-        super.onViewDetachedFromWindow(holder);
-    }
-
     private void setTopMargin(View view, int topMargin) {
         ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
         lp.topMargin = topMargin;
diff --git a/src/com/android/tv/dvr/ui/DetailsViewBackgroundHelper.java b/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
similarity index 97%
rename from src/com/android/tv/dvr/ui/DetailsViewBackgroundHelper.java
rename to src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
index 6714ecd..82fe9ce 100644
--- a/src/com/android/tv/dvr/ui/DetailsViewBackgroundHelper.java
+++ b/src/com/android/tv/dvr/ui/browse/DetailsViewBackgroundHelper.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.app.Activity;
 import android.graphics.drawable.BitmapDrawable;
@@ -26,7 +26,7 @@
 /**
  * The Background Helper.
  */
-public class DetailsViewBackgroundHelper {
+class DetailsViewBackgroundHelper {
     // Background delay serves to avoid kicking off expensive bitmap loading
     // in case multiple backgrounds are set in quick succession.
     private static final int SET_BACKGROUND_DELAY_MS = 100;
diff --git a/src/com/android/tv/dvr/ui/DvrActivity.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
similarity index 61%
rename from src/com/android/tv/dvr/ui/DvrActivity.java
rename to src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
index 45fb1cf..07eec10 100644
--- a/src/com/android/tv/dvr/ui/DvrActivity.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseActivity.java
@@ -14,9 +14,11 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.app.Activity;
+import android.content.Intent;
+import android.media.tv.TvInputManager;
 import android.os.Bundle;
 
 import com.android.tv.R;
@@ -25,11 +27,26 @@
 /**
  * {@link android.app.Activity} for DVR UI.
  */
-public class DvrActivity extends Activity {
+public class DvrBrowseActivity extends Activity {
+    private DvrBrowseFragment mFragment;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         TvApplication.setCurrentRunningProcess(this, true);
         super.onCreate(savedInstanceState);
         setContentView(R.layout.dvr_main);
+        mFragment = (DvrBrowseFragment) getFragmentManager().findFragmentById(R.id.dvr_frame);
+        handleIntent(getIntent());
     }
-}
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        handleIntent(intent);
+    }
+
+    private void handleIntent(Intent intent) {
+        if (TvInputManager.ACTION_VIEW_RECORDING_SCHEDULES.equals(intent.getAction())) {
+            mFragment.showScheduledRow();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/DvrBrowseFragment.java b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
similarity index 79%
rename from src/com/android/tv/dvr/ui/DvrBrowseFragment.java
rename to src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
index a6dd31d..cb3a574 100644
--- a/src/com/android/tv/dvr/ui/DvrBrowseFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrBrowseFragment.java
@@ -14,10 +14,9 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.content.Context;
-import android.media.tv.TvInputManager.TvInputCallback;
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.v17.leanback.app.BrowseFragment;
@@ -25,11 +24,11 @@
 import android.support.v17.leanback.widget.ClassPresenterSelector;
 import android.support.v17.leanback.widget.HeaderItem;
 import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
 import android.support.v17.leanback.widget.Presenter;
 import android.support.v17.leanback.widget.TitleViewAdapter;
-import android.text.TextUtils;
 import android.util.Log;
+import android.view.View;
+import android.view.ViewTreeObserver.OnGlobalFocusChangeListener;
 
 import com.android.tv.ApplicationSingletons;
 import com.android.tv.R;
@@ -42,9 +41,10 @@
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
 import com.android.tv.dvr.DvrDataManager.SeriesRecordingListener;
 import com.android.tv.dvr.DvrScheduleManager;
-import com.android.tv.dvr.RecordedProgram;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.ui.SortedArrayAdapter;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -64,12 +64,16 @@
     private static final int MAX_RECENT_ITEM_COUNT = 10;
     private static final int MAX_SCHEDULED_ITEM_COUNT = 4;
 
+    private boolean mShouldShowScheduleRow;
+    private boolean mEntranceTransitionEnded;
+
     private RecordedProgramAdapter mRecentAdapter;
     private ScheduleAdapter mScheduleAdapter;
     private SeriesAdapter mSeriesAdapter;
     private RecordedProgramAdapter[] mGenreAdapters =
             new RecordedProgramAdapter[GenreItems.getGenreCount() + 1];
     private ListRow mRecentRow;
+    private ListRow mScheduledRow;
     private ListRow mSeriesRow;
     private ListRow[] mGenreRows = new ListRow[GenreItems.getGenreCount() + 1];
     private List<String> mGenreLabels;
@@ -79,6 +83,20 @@
     private ClassPresenterSelector mPresenterSelector;
     private final HashMap<String, RecordedProgram> mSeriesId2LatestProgram = new HashMap<>();
     private final Handler mHandler = new Handler();
+    private final OnGlobalFocusChangeListener mOnGlobalFocusChangeListener =
+            new OnGlobalFocusChangeListener() {
+                @Override
+                public void onGlobalFocusChanged(View oldFocus, View newFocus) {
+                    if (oldFocus instanceof RecordingCardView) {
+                        ((RecordingCardView) oldFocus).expandTitle(false, true);
+                    }
+                    if (newFocus instanceof RecordingCardView) {
+                        // If the header transition is ongoing, expand cards immediately without
+                        // animation to make a smooth transition.
+                        ((RecordingCardView) newFocus).expandTitle(true, !isInHeadersTransition());
+                    }
+                }
+            };
 
     private final Comparator<Object> RECORDED_PROGRAM_COMPARATOR = new Comparator<Object>() {
         @Override
@@ -104,7 +122,7 @@
         }
     };
 
-    private final Comparator<Object> SCHEDULE_COMPARATOR = new Comparator<Object>() {
+    private static final Comparator<Object> SCHEDULE_COMPARATOR = new Comparator<Object>() {
         @Override
         public int compare(Object lhs, Object rhs) {
             if (lhs instanceof ScheduledRecording) {
@@ -128,7 +146,7 @@
         public void onConflictStateChange(boolean conflict, ScheduledRecording... schedules) {
             if (mScheduleAdapter != null) {
                 for (ScheduledRecording schedule : schedules) {
-                    onScheduledRecordingStatusChanged(schedule);
+                    onScheduledRecordingConflictStatusChanged(schedule);
                 }
             }
         }
@@ -154,16 +172,12 @@
                         new ScheduledRecordingPresenter(context))
                 .addClassPresenter(RecordedProgram.class, new RecordedProgramPresenter(context))
                 .addClassPresenter(SeriesRecording.class, new SeriesRecordingPresenter(context))
-                .addClassPresenter(FullScheduleCardHolder.class, new FullSchedulesCardPresenter());
+                .addClassPresenter(FullScheduleCardHolder.class,
+                        new FullSchedulesCardPresenter(context));
         mGenreLabels = new ArrayList<>(Arrays.asList(GenreItems.getLabels(context)));
         mGenreLabels.add(getString(R.string.dvr_main_others));
-        setupUiElements();
-        setupAdapters();
-        mDvrScheudleManager.addOnConflictStateChangeListener(mOnConflictStateChangeListener);
-        prepareEntranceTransition();
-        if (mDvrDataManager.isInitialized()) {
-            startEntranceTransition();
-        } else {
+        prepareUiElements();
+        if (!startBrowseIfDvrInitialized()) {
             if (!mDvrDataManager.isDvrScheduleLoadFinished()) {
                 mDvrDataManager.addDvrScheduleLoadFinishedListener(this);
             }
@@ -174,6 +188,19 @@
     }
 
     @Override
+    public void onViewCreated(View view, Bundle savedInstanceState) {
+        super.onViewCreated(view, savedInstanceState);
+        view.getViewTreeObserver().addOnGlobalFocusChangeListener(mOnGlobalFocusChangeListener);
+    }
+
+    @Override
+    public void onDestroyView() {
+        getView().getViewTreeObserver()
+                .removeOnGlobalFocusChangeListener(mOnGlobalFocusChangeListener);
+        super.onDestroyView();
+    }
+
+    @Override
     public void onDestroy() {
         if (DEBUG) Log.d(TAG, "onDestroy");
         mHandler.removeCallbacks(mUpdateRowsRunnable);
@@ -195,25 +222,13 @@
 
     @Override
     public void onDvrScheduleLoadFinished() {
-        List<ScheduledRecording> scheduledRecordings = mDvrDataManager.getAllScheduledRecordings();
-        onScheduledRecordingAdded(ScheduledRecording.toArray(scheduledRecordings));
-        List<SeriesRecording> seriesRecordings = mDvrDataManager.getSeriesRecordings();
-        onSeriesRecordingAdded(SeriesRecording.toArray(seriesRecordings));
-        if (mDvrDataManager.isInitialized()) {
-            startEntranceTransition();
-        }
+        startBrowseIfDvrInitialized();
         mDvrDataManager.removeDvrScheduleLoadFinishedListener(this);
     }
 
     @Override
     public void onRecordedProgramLoadFinished() {
-        for (RecordedProgram recordedProgram : mDvrDataManager.getRecordedPrograms()) {
-            handleRecordedProgramAdded(recordedProgram, true);
-        }
-        updateRows();
-        if (mDvrDataManager.isInitialized()) {
-            startEntranceTransition();
-        }
+        startBrowseIfDvrInitialized();
         mDvrDataManager.removeRecordedProgramLoadFinishedListener(this);
     }
 
@@ -270,6 +285,18 @@
         }
     }
 
+    private void onScheduledRecordingConflictStatusChanged(ScheduledRecording... schedules) {
+        for (ScheduledRecording schedule : schedules) {
+            if (needToShowScheduledRecording(schedule)) {
+                if (mScheduleAdapter.contains(schedule)) {
+                    mScheduleAdapter.change(schedule);
+                }
+            } else {
+                mScheduleAdapter.removeWithId(schedule);
+            }
+        }
+    }
+
     @Override
     public void onSeriesRecordingAdded(SeriesRecording... seriesRecordings) {
         handleSeriesRecordingsAdded(Arrays.asList(seriesRecordings));
@@ -295,44 +322,80 @@
         super.showTitle(flags);
     }
 
-    private void setupUiElements() {
+    @Override
+    protected void onEntranceTransitionEnd() {
+        super.onEntranceTransitionEnd();
+        if (mShouldShowScheduleRow) {
+            showScheduledRowInternal();
+        }
+        mEntranceTransitionEnded = true;
+    }
+
+    void showScheduledRow() {
+        if (!mEntranceTransitionEnded) {
+            setHeadersState(HEADERS_HIDDEN);
+            mShouldShowScheduleRow = true;
+        } else {
+            showScheduledRowInternal();
+        }
+    }
+
+    private void showScheduledRowInternal() {
+        setSelectedPosition(mRowsAdapter.indexOf(mScheduledRow), true, null);
+        if (getHeadersState() == HEADERS_ENABLED) {
+            startHeadersTransition(false);
+        }
+        mShouldShowScheduleRow = false;
+    }
+
+    private void prepareUiElements() {
         setBadgeDrawable(getActivity().getDrawable(R.drawable.ic_dvr_badge));
         setHeadersState(HEADERS_ENABLED);
         setHeadersTransitionOnBackEnabled(false);
         setBrandColor(getResources().getColor(R.color.program_guide_side_panel_background, null));
+        mRowsAdapter = new ArrayObjectAdapter(new DvrListRowPresenter(getContext()));
+        setAdapter(mRowsAdapter);
+        prepareEntranceTransition();
     }
 
-    private void setupAdapters() {
-        mRecentAdapter = new RecordedProgramAdapter(MAX_RECENT_ITEM_COUNT);
-        mScheduleAdapter = new ScheduleAdapter(MAX_SCHEDULED_ITEM_COUNT);
-        mSeriesAdapter = new SeriesAdapter();
-        for (int i = 0; i < mGenreAdapters.length; i++) {
-            mGenreAdapters[i] = new RecordedProgramAdapter();
+    private boolean startBrowseIfDvrInitialized() {
+        if (mDvrDataManager.isInitialized()) {
+            // Setup rows
+            mRecentAdapter = new RecordedProgramAdapter(MAX_RECENT_ITEM_COUNT);
+            mScheduleAdapter = new ScheduleAdapter(MAX_SCHEDULED_ITEM_COUNT);
+            mSeriesAdapter = new SeriesAdapter();
+            for (int i = 0; i < mGenreAdapters.length; i++) {
+                mGenreAdapters[i] = new RecordedProgramAdapter();
+            }
+            // Schedule Recordings.
+            List<ScheduledRecording> schedules = mDvrDataManager.getAllScheduledRecordings();
+            onScheduledRecordingAdded(ScheduledRecording.toArray(schedules));
+            mScheduleAdapter.addExtraItem(FullScheduleCardHolder.FULL_SCHEDULE_CARD_HOLDER);
+            // Recorded Programs.
+            for (RecordedProgram recordedProgram : mDvrDataManager.getRecordedPrograms()) {
+                handleRecordedProgramAdded(recordedProgram, false);
+            }
+            // Series Recordings. Series recordings should be added after recorded programs, because
+            // we build series recordings' latest program information while adding recorded programs.
+            List<SeriesRecording> recordings = mDvrDataManager.getSeriesRecordings();
+            handleSeriesRecordingsAdded(recordings);
+            mRecentRow = new ListRow(new HeaderItem(
+                    getString(R.string.dvr_main_recent)), mRecentAdapter);
+            mScheduledRow = new ListRow(new HeaderItem(
+                    getString(R.string.dvr_main_scheduled)), mScheduleAdapter);
+            mSeriesRow = new ListRow(new HeaderItem(
+                    getString(R.string.dvr_main_series)), mSeriesAdapter);
+            mRowsAdapter.add(mScheduledRow);
+            updateRows();
+            // Initialize listeners
+            mDvrDataManager.addRecordedProgramListener(this);
+            mDvrDataManager.addScheduledRecordingListener(this);
+            mDvrDataManager.addSeriesRecordingListener(this);
+            mDvrScheudleManager.addOnConflictStateChangeListener(mOnConflictStateChangeListener);
+            startEntranceTransition();
+            return true;
         }
-        // Schedule Recordings.
-        List<ScheduledRecording> schedules = mDvrDataManager.getAllScheduledRecordings();
-        onScheduledRecordingAdded(ScheduledRecording.toArray(schedules));
-        mScheduleAdapter.addExtraItem(FullScheduleCardHolder.FULL_SCHEDULE_CARD_HOLDER);
-        // Recorded Programs.
-        for (RecordedProgram recordedProgram : mDvrDataManager.getRecordedPrograms()) {
-            handleRecordedProgramAdded(recordedProgram, false);
-        }
-        // Series Recordings. Series recordings should be added after recorded programs, because
-        // we build series recordings' latest program information while adding recorded programs.
-        List<SeriesRecording> recordings = mDvrDataManager.getSeriesRecordings();
-        handleSeriesRecordingsAdded(recordings);
-        mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
-        mRecentRow = new ListRow(new HeaderItem(
-                getString(R.string.dvr_main_recent)), mRecentAdapter);
-        mRowsAdapter.add(new ListRow(new HeaderItem(
-                getString(R.string.dvr_main_scheduled)), mScheduleAdapter));
-        mSeriesRow = new ListRow(new HeaderItem(
-                getString(R.string.dvr_main_series)), mSeriesAdapter);
-        updateRows();
-        mDvrDataManager.addRecordedProgramListener(this);
-        mDvrDataManager.addScheduledRecordingListener(this);
-        mDvrDataManager.addSeriesRecordingListener(this);
-        setAdapter(mRowsAdapter);
+        return false;
     }
 
     private void handleRecordedProgramAdded(RecordedProgram recordedProgram,
@@ -589,10 +652,11 @@
 
         @Override
         public long getId(Object item) {
+            // We takes the inverse number for the ID of recorded programs to make the ID stable.
             if (item instanceof SeriesRecording) {
                 return ((SeriesRecording) item).getId();
             } else if (item instanceof RecordedProgram) {
-                return ((RecordedProgram) item).getId();
+                return -((RecordedProgram) item).getId() - 1;
             } else {
                 return -1;
             }
diff --git a/src/com/android/tv/dvr/ui/DvrDetailsActivity.java b/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java
similarity index 61%
rename from src/com/android/tv/dvr/ui/DvrDetailsActivity.java
rename to src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java
index 806c775..35d21db 100644
--- a/src/com/android/tv/dvr/ui/DvrDetailsActivity.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrDetailsActivity.java
@@ -14,19 +14,23 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.app.Activity;
 import android.os.Bundle;
 import android.support.v17.leanback.app.DetailsFragment;
 
+import android.transition.Transition;
+import android.transition.Transition.TransitionListener;
+import android.view.View;
 import com.android.tv.R;
 import com.android.tv.TvApplication;
+import com.android.tv.dialog.PinDialogFragment;
 
 /**
  * Activity to show details view in DVR.
  */
-public class DvrDetailsActivity extends Activity {
+public class DvrDetailsActivity extends Activity implements PinDialogFragment.OnPinCheckedListener {
     /**
      * Name of record id added to the Intent.
      */
@@ -68,6 +72,8 @@
      */
     public static final int SERIES_RECORDING_VIEW = 4;
 
+    private PinDialogFragment.OnPinCheckedListener mOnPinCheckedListener;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         TvApplication.setCurrentRunningProcess(this, true);
@@ -94,5 +100,55 @@
             getFragmentManager().beginTransaction()
                     .replace(R.id.dvr_details_view_frame, detailsFragment).commit();
         }
+
+        // This is a workaround for the focus on O device
+        addTransitionListener();
+    }
+
+    @Override
+    public void onPinChecked(boolean checked, int type, String rating) {
+        if (mOnPinCheckedListener != null) {
+            mOnPinCheckedListener.onPinChecked(checked, type, rating);
+        }
+    }
+
+    void setOnPinCheckListener(PinDialogFragment.OnPinCheckedListener listener) {
+        mOnPinCheckedListener = listener;
+    }
+
+    private void addTransitionListener() {
+        getWindow()
+                .getSharedElementEnterTransition()
+                .addListener(
+                        new TransitionListener() {
+                            @Override
+                            public void onTransitionStart(Transition transition) {
+                                // Do nothing
+                            }
+
+                            @Override
+                            public void onTransitionEnd(Transition transition) {
+                                View actions = findViewById(R.id.details_overview_actions);
+                                if (actions != null) {
+                                    actions.requestFocus();
+                                }
+                            }
+
+                            @Override
+                            public void onTransitionCancel(Transition transition) {
+                                // Do nothing
+
+                            }
+
+                            @Override
+                            public void onTransitionPause(Transition transition) {
+                                // Do nothing
+                            }
+
+                            @Override
+                            public void onTransitionResume(Transition transition) {
+                                // Do nothing
+                            }
+                        });
     }
 }
diff --git a/src/com/android/tv/dvr/ui/DvrDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
similarity index 79%
rename from src/com/android/tv/dvr/ui/DvrDetailsFragment.java
rename to src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
index 21f9c4b..19fb711 100644
--- a/src/com/android/tv/dvr/ui/DvrDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/DvrDetailsFragment.java
@@ -14,16 +14,14 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.media.tv.TvContentRating;
-import android.media.tv.TvInputManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.annotation.Nullable;
@@ -36,20 +34,18 @@
 import android.support.v17.leanback.widget.PresenterSelector;
 import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
 import android.support.v17.leanback.widget.VerticalGridView;
-import android.text.Spannable;
-import android.text.SpannableString;
 import android.text.TextUtils;
-import android.text.style.TextAppearanceSpan;
 import android.widget.Toast;
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.data.BaseProgram;
+import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.dialog.PinDialogFragment;
-import com.android.tv.dvr.DvrPlaybackActivity;
-import com.android.tv.dvr.RecordedProgram;
+import com.android.tv.dialog.PinDialogFragment.OnPinCheckedListener;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.parental.ParentalControlSettings;
 import com.android.tv.util.ImageLoader;
 import com.android.tv.util.ToastUtils;
@@ -163,26 +159,6 @@
     abstract OnActionClickedListener onCreateOnActionClickedListener();
 
     /**
-     * Returns program title with episode number. If the program is null, returns channel name.
-     */
-    protected CharSequence getTitleFromProgram(BaseProgram program, Channel channel) {
-        String titleWithEpisodeNumber = program.getTitleWithEpisodeNumber(getContext());
-        SpannableString title = titleWithEpisodeNumber == null ? null
-                : new SpannableString(titleWithEpisodeNumber);
-        if (TextUtils.isEmpty(title)) {
-            title = new SpannableString(channel != null ? channel.getDisplayName()
-                    : getContext().getResources().getString(
-                    R.string.no_program_information));
-        } else {
-            String programTitle = program.getTitle();
-            title.setSpan(new TextAppearanceSpan(getContext(),
-                    R.style.text_appearance_card_view_episode_number), programTitle == null ? 0
-                    : programTitle.length(), title.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
-        }
-        return title;
-    }
-
-    /**
      * Loads logo and background images for detail fragments.
      */
     protected void onLoadLogoAndBackgroundImages(DetailsContent detailsContent) {
@@ -233,10 +209,11 @@
                     Toast.LENGTH_SHORT);
             return;
         }
+        long programId = recordedProgram.getId();
         ParentalControlSettings parental = TvApplication.getSingletons(getActivity())
                 .getTvInputManagerHelper().getParentalControlSettings();
         if (!parental.isParentalControlsEnabled()) {
-            launchPlaybackActivity(recordedProgram, seekTimeMs, false);
+            DvrUiHelper.startPlaybackActivity(getContext(), programId, seekTimeMs, false);
             return;
         }
         ChannelDataManager channelDataManager =
@@ -246,21 +223,12 @@
             checkPinToPlay(recordedProgram, seekTimeMs);
             return;
         }
-        String ratingString = recordedProgram.getContentRating();
-        if (TextUtils.isEmpty(ratingString)) {
-            launchPlaybackActivity(recordedProgram, seekTimeMs, false);
-            return;
-        }
-        String[] ratingList = ratingString.split(",");
-        TvContentRating[] programRatings = new TvContentRating[ratingList.length];
-        for (int i = 0; i < ratingList.length; i++) {
-            programRatings[i] = TvContentRating.unflattenFromString(ratingList[i]);
-        }
-        TvContentRating blockRatings = parental.getBlockedRating(programRatings);
+        TvContentRating[] ratings = recordedProgram.getContentRatings();
+        TvContentRating blockRatings = parental.getBlockedRating(ratings);
         if (blockRatings != null) {
             checkPinToPlay(recordedProgram, seekTimeMs);
         } else {
-            launchPlaybackActivity(recordedProgram, seekTimeMs, false);
+            DvrUiHelper.startPlaybackActivity(getContext(), programId, seekTimeMs, false);
         }
     }
 
@@ -279,26 +247,21 @@
     }
 
     private void checkPinToPlay(RecordedProgram recordedProgram, long seekTimeMs) {
-        new PinDialogFragment(PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM,
-                new PinDialogFragment.ResultListener() {
-                    @Override
-                    public void done(boolean success) {
-                        if (success) {
-                            launchPlaybackActivity(recordedProgram, seekTimeMs, true);
-                        }
+        SoftPreconditions.checkState(getActivity() instanceof DvrDetailsActivity);
+        if (getActivity() instanceof DvrDetailsActivity) {
+            ((DvrDetailsActivity) getActivity()).setOnPinCheckListener(new OnPinCheckedListener() {
+                @Override
+                public void onPinChecked(boolean checked, int type, String rating) {
+                    ((DvrDetailsActivity) getActivity()).setOnPinCheckListener(null);
+                    if (checked && type == PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM) {
+                        DvrUiHelper.startPlaybackActivity(getContext(), recordedProgram.getId(),
+                                seekTimeMs, true);
                     }
-                }).show(getActivity().getFragmentManager(), PinDialogFragment.DIALOG_TAG);
-    }
-
-    private void launchPlaybackActivity(RecordedProgram mRecordedProgram, long seekTimeMs,
-            boolean pinChecked) {
-        Intent intent = new Intent(getActivity(), DvrPlaybackActivity.class);
-        intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, mRecordedProgram.getId());
-        if (seekTimeMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
-            intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_SEEK_TIME, seekTimeMs);
+                }
+            });
+            PinDialogFragment.create(PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_PROGRAM)
+                    .show(getActivity().getFragmentManager(), PinDialogFragment.DIALOG_TAG);
         }
-        intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_PIN_CHECKED, pinChecked);
-        getActivity().startActivity(intent);
     }
 
     private static class MyImageLoaderCallback extends
diff --git a/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java b/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java
new file mode 100644
index 0000000..df0e61c
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/DvrItemPresenter.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.browse;
+
+import android.app.Activity;
+import android.content.Context;
+import android.support.annotation.CallSuper;
+import android.support.v17.leanback.widget.Presenter;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+
+import com.android.tv.common.SoftPreconditions;
+import com.android.tv.dvr.ui.DvrUiHelper;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An abstract class to present DVR items in {@link RecordingCardView}, which is mainly used in
+ * {@link DvrBrowseFragment}. DVR items might include:
+ * {@link com.android.tv.dvr.data.ScheduledRecording},
+ * {@link com.android.tv.dvr.data.RecordedProgram}, and
+ * {@link com.android.tv.dvr.data.SeriesRecording}.
+ */
+public abstract class DvrItemPresenter<T> extends Presenter {
+    protected final Context mContext;
+    private final Set<DvrItemViewHolder> mBoundViewHolders = new HashSet<>();
+    private final OnClickListener mOnClickListener = onCreateOnClickListener();
+
+    protected class DvrItemViewHolder extends ViewHolder {
+        DvrItemViewHolder(RecordingCardView view) {
+            super(view);
+        }
+
+        protected RecordingCardView getView() {
+            return (RecordingCardView) view;
+        }
+
+        protected void onBound(T item) { }
+
+        protected void onUnbound() { }
+    }
+
+    DvrItemPresenter(Context context) {
+        mContext = context;
+    }
+
+    @Override
+    public final ViewHolder onCreateViewHolder(ViewGroup parent) {
+        return onCreateDvrItemViewHolder();
+    }
+
+    @Override
+    public final void onBindViewHolder(ViewHolder baseHolder, Object item) {
+        DvrItemViewHolder viewHolder;
+        T dvrItem;
+        try {
+            viewHolder = (DvrItemViewHolder) baseHolder;
+            Class<T> itemType = (Class<T>) item.getClass();
+            dvrItem = itemType.cast(item);
+        } catch (ClassCastException e) {
+            SoftPreconditions.checkState(false);
+            return;
+        }
+        viewHolder.view.setTag(item);
+        viewHolder.view.setOnClickListener(mOnClickListener);
+        onBindDvrItemViewHolder(viewHolder, dvrItem);
+        viewHolder.onBound(dvrItem);
+        mBoundViewHolders.add(viewHolder);
+    }
+
+    @Override
+    @CallSuper
+    public void onUnbindViewHolder(ViewHolder baseHolder) {
+        DvrItemViewHolder viewHolder = (DvrItemViewHolder) baseHolder;
+        mBoundViewHolders.remove(viewHolder);
+        viewHolder.onUnbound();
+        viewHolder.view.setTag(null);
+        viewHolder.view.setOnClickListener(null);
+    }
+
+    /**
+     * Unbinds all bound view holders.
+     */
+    public void unbindAllViewHolders() {
+        // When browse fragments are destroyed, RecyclerView would not call presenters'
+        // onUnbindViewHolder(). We should handle it by ourselves to prevent resources leaks.
+        for (ViewHolder viewHolder : new HashSet<>(mBoundViewHolders)) {
+            onUnbindViewHolder(viewHolder);
+        }
+    }
+
+    /**
+     * This method will be called when a {@link DvrItemViewHolder} is needed to be created.
+     */
+    abstract protected DvrItemViewHolder onCreateDvrItemViewHolder();
+
+    /**
+     * This method will be called when a {@link DvrItemViewHolder} is bound to a DVR item.
+     */
+    abstract protected void onBindDvrItemViewHolder(DvrItemViewHolder viewHolder, T item);
+
+    /**
+     * Returns context.
+     */
+    protected Context getContext() {
+        return mContext;
+    }
+
+    /**
+     * Creates {@link OnClickListener} for DVR library's card views.
+     */
+    protected OnClickListener onCreateOnClickListener() {
+        return new OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                if (view instanceof RecordingCardView) {
+                    RecordingCardView v = (RecordingCardView) view;
+                    DvrUiHelper.startDetailsActivity((Activity) v.getContext(),
+                            v.getTag(), v.getImageView(), false);
+                }
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java b/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java
new file mode 100644
index 0000000..37a72ea
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/DvrListRowPresenter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017 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.dvr.ui.browse;
+
+import android.content.Context;
+import android.support.v17.leanback.widget.ListRowPresenter;
+import android.view.ViewGroup;
+
+import com.android.tv.R;
+
+/** A list row presenter to display expand/fold card views list. */
+public class DvrListRowPresenter extends ListRowPresenter {
+    public DvrListRowPresenter(Context context) {
+        super();
+        setRowHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
+        setExpandedRowHeight(
+                context.getResources()
+                        .getDimensionPixelSize(R.dimen.dvr_library_expanded_row_height));
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/FullScheduleCardHolder.java b/src/com/android/tv/dvr/ui/browse/FullScheduleCardHolder.java
similarity index 95%
rename from src/com/android/tv/dvr/ui/FullScheduleCardHolder.java
rename to src/com/android/tv/dvr/ui/browse/FullScheduleCardHolder.java
index d4d4d8a..311137a 100644
--- a/src/com/android/tv/dvr/ui/FullScheduleCardHolder.java
+++ b/src/com/android/tv/dvr/ui/browse/FullScheduleCardHolder.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 /**
  * Special object for schedule preview;
diff --git a/src/com/android/tv/dvr/ui/browse/FullSchedulesCardPresenter.java b/src/com/android/tv/dvr/ui/browse/FullSchedulesCardPresenter.java
new file mode 100644
index 0000000..94c67ee
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/FullSchedulesCardPresenter.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.browse;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.ui.DvrUiHelper;
+import com.android.tv.util.Utils;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Presents a {@link ScheduledRecording} in the {@link DvrBrowseFragment}.
+ */
+class FullSchedulesCardPresenter extends DvrItemPresenter<Object> {
+    private final Drawable mIconDrawable;
+    private final String mCardTitleText;
+
+    FullSchedulesCardPresenter(Context context) {
+        super(context);
+        mIconDrawable = mContext.getDrawable(R.drawable.dvr_full_schedule);
+        mCardTitleText = mContext.getString(R.string.dvr_full_schedule_card_view_title);
+    }
+
+    @Override
+    public DvrItemViewHolder onCreateDvrItemViewHolder() {
+        return new DvrItemViewHolder(new RecordingCardView(mContext));
+    }
+
+    @Override
+    public void onBindDvrItemViewHolder(DvrItemViewHolder vh, Object o) {
+        final RecordingCardView cardView = (RecordingCardView) vh.view;
+
+        cardView.setTitle(mCardTitleText);
+        cardView.setImage(mIconDrawable);
+        List<ScheduledRecording> scheduledRecordings = TvApplication.getSingletons(mContext)
+                .getDvrDataManager().getAvailableScheduledRecordings();
+        int fullDays = 0;
+        if (!scheduledRecordings.isEmpty()) {
+            fullDays = Utils.computeDateDifference(System.currentTimeMillis(),
+                    Collections.max(scheduledRecordings, ScheduledRecording.START_TIME_COMPARATOR)
+                    .getStartTimeMs()) + 1;
+        }
+        cardView.setContent(mContext.getResources().getQuantityString(
+                R.plurals.dvr_full_schedule_card_view_content, fullDays, fullDays), null);
+    }
+
+    @Override
+    public void onUnbindViewHolder(ViewHolder vh) {
+        ((RecordingCardView) vh.view).reset();
+        super.onUnbindViewHolder(vh);
+    }
+
+    @Override
+    protected View.OnClickListener onCreateOnClickListener() {
+        return new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                DvrUiHelper.startSchedulesActivity(mContext, null);
+            }
+        };
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/RecordedProgramDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
similarity index 80%
rename from src/com/android/tv/dvr/ui/RecordedProgramDetailsFragment.java
rename to src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
index e698b8a..eb9cb26 100644
--- a/src/com/android/tv/dvr/ui/RecordedProgramDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/RecordedProgramDetailsFragment.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.content.res.Resources;
 import android.media.tv.TvInputManager;
@@ -22,18 +22,16 @@
 import android.support.v17.leanback.widget.Action;
 import android.support.v17.leanback.widget.OnActionClickedListener;
 import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
-import android.text.TextUtils;
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.data.Channel;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.DvrWatchedPositionManager;
-import com.android.tv.dvr.RecordedProgram;
+import com.android.tv.dvr.data.RecordedProgram;
 
 /**
- * {@link DetailsFragment} for recorded program in DVR.
+ * {@link android.support.v17.leanback.app.DetailsFragment} for recorded program in DVR.
  */
 public class RecordedProgramDetailsFragment extends DvrDetailsFragment
         implements DvrDataManager.RecordedProgramListener {
@@ -44,7 +42,6 @@
     private DvrWatchedPositionManager mDvrWatchedPositionManager;
 
     private RecordedProgram mRecordedProgram;
-    private DetailsContent mDetailsContent;
     private boolean mPaused;
     private DvrDataManager mDvrDataManager;
 
@@ -59,7 +56,8 @@
     public void onCreateInternal() {
         mDvrWatchedPositionManager = TvApplication.getSingletons(getActivity())
                 .getDvrWatchedPositionManager();
-        setDetailsOverviewRow(mDetailsContent);
+        setDetailsOverviewRow(DetailsContent
+                .createFromRecordedProgram(getContext(), mRecordedProgram));
     }
 
     @Override
@@ -87,26 +85,7 @@
     protected boolean onLoadRecordingDetails(Bundle args) {
         long recordedProgramId = args.getLong(DvrDetailsActivity.RECORDING_ID);
         mRecordedProgram = mDvrDataManager.getRecordedProgram(recordedProgramId);
-        if (mRecordedProgram == null) {
-            // notify super class to end activity before initializing anything
-            return false;
-        }
-        mDetailsContent = createDetailsContent();
-        return true;
-    }
-
-    private DetailsContent createDetailsContent() {
-        Channel channel = TvApplication.getSingletons(getContext()).getChannelDataManager()
-                .getChannel(mRecordedProgram.getChannelId());
-        String description = TextUtils.isEmpty(mRecordedProgram.getLongDescription())
-                ? mRecordedProgram.getDescription() : mRecordedProgram.getLongDescription();
-        return new DetailsContent.Builder()
-                .setTitle(getTitleFromProgram(mRecordedProgram, channel))
-                .setStartTimeUtcMillis(mRecordedProgram.getStartTimeUtcMillis())
-                .setEndTimeUtcMillis(mRecordedProgram.getEndTimeUtcMillis())
-                .setDescription(description)
-                .setImageUris(mRecordedProgram, channel)
-                .build();
+        return mRecordedProgram != null;
     }
 
     @Override
diff --git a/src/com/android/tv/dvr/ui/browse/RecordedProgramPresenter.java b/src/com/android/tv/dvr/ui/browse/RecordedProgramPresenter.java
new file mode 100644
index 0000000..5fe162b
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/RecordedProgramPresenter.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.browse;
+
+import android.content.Context;
+import android.media.tv.TvInputManager;
+
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.dvr.DvrWatchedPositionManager;
+import com.android.tv.dvr.DvrWatchedPositionManager.WatchedPositionChangedListener;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.util.Utils;
+
+/**
+ * Presents a {@link RecordedProgram} in the {@link DvrBrowseFragment}.
+ */
+public class RecordedProgramPresenter extends DvrItemPresenter<RecordedProgram> {
+    private final DvrWatchedPositionManager mDvrWatchedPositionManager;
+    private String mTodayString;
+    private String mYesterdayString;
+    private final int mProgressBarColor;
+    private final boolean mShowEpisodeTitle;
+    private final boolean mExpandTitleWhenFocused;
+
+    protected final class RecordedProgramViewHolder extends DvrItemViewHolder
+            implements WatchedPositionChangedListener {
+        private RecordedProgram mProgram;
+        private boolean mShowProgress;
+
+        public RecordedProgramViewHolder(RecordingCardView view, Integer progressColor) {
+            super(view);
+            if (progressColor == null) {
+                mShowProgress = false;
+            } else {
+                mShowProgress = true;
+                view.setProgressBarColor(progressColor);
+            }
+        }
+
+        private void setProgressBar(long watchedPositionMs) {
+            ((RecordingCardView) view).setProgressBar(
+                    (watchedPositionMs == TvInputManager.TIME_SHIFT_INVALID_TIME) ? null
+                            : Math.min(100, (int) (100.0f * watchedPositionMs
+                                    / mProgram.getDurationMillis())));
+        }
+
+        @Override
+        public void onWatchedPositionChanged(long programId, long positionMs) {
+            if (programId == mProgram.getId()) {
+                setProgressBar(positionMs);
+            }
+        }
+
+        @Override
+        protected void onBound(RecordedProgram program) {
+            mProgram = program;
+            if (mShowProgress) {
+                mDvrWatchedPositionManager.addListener(this, program.getId());
+                setProgressBar(mDvrWatchedPositionManager.getWatchedPosition(program.getId()));
+            } else {
+                getView().setProgressBar(null);
+            }
+        }
+
+        @Override
+        protected void onUnbound() {
+            if (mShowProgress) {
+                mDvrWatchedPositionManager.removeListener(this, mProgram.getId());
+            }
+            getView().reset();
+        }
+    }
+
+    RecordedProgramPresenter(Context context, boolean showEpisodeTitle,
+            boolean expandTitleWhenFocused) {
+        super(context);
+        mTodayString = mContext.getString(R.string.dvr_date_today);
+        mYesterdayString = mContext.getString(R.string.dvr_date_yesterday);
+        mDvrWatchedPositionManager =
+                TvApplication.getSingletons(mContext).getDvrWatchedPositionManager();
+        mProgressBarColor = mContext.getResources()
+                .getColor(R.color.play_controls_progress_bar_watched);
+        mShowEpisodeTitle = showEpisodeTitle;
+        mExpandTitleWhenFocused = expandTitleWhenFocused;
+    }
+
+    public RecordedProgramPresenter(Context context) {
+        this(context, false, false);
+    }
+
+    @Override
+    public DvrItemViewHolder onCreateDvrItemViewHolder() {
+        return new RecordedProgramViewHolder(
+                new RecordingCardView(mContext, mExpandTitleWhenFocused), mProgressBarColor);
+    }
+
+    @Override
+    public void onBindDvrItemViewHolder(DvrItemViewHolder baseHolder, RecordedProgram program) {
+        final RecordedProgramViewHolder viewHolder = (RecordedProgramViewHolder) baseHolder;
+        final RecordingCardView cardView = viewHolder.getView();
+        DetailsContent details = DetailsContent.createFromRecordedProgram(mContext, program);
+        cardView.setTitle(mShowEpisodeTitle ?
+                program.getEpisodeDisplayTitle(mContext) : details.getTitle());
+        cardView.setImageUri(details.getLogoImageUri(), details.isUsingChannelLogo());
+        cardView.setContent(generateMajorContent(program), generateMinorContent(program));
+        cardView.setDetailBackgroundImageUri(details.getBackgroundImageUri());
+    }
+
+    private String generateMajorContent(RecordedProgram program) {
+        int dateDifference = Utils.computeDateDifference(program.getStartTimeUtcMillis(),
+                System.currentTimeMillis());
+        if (dateDifference == 0) {
+            return mTodayString;
+        } else if (dateDifference == 1) {
+            return mYesterdayString;
+        } else {
+            return Utils.getDurationString(mContext, program.getStartTimeUtcMillis(),
+                    program.getStartTimeUtcMillis(), false, true, false, 0);
+        }
+    }
+
+    private String generateMinorContent(RecordedProgram program) {
+        int durationMinutes = Math.max(1, Utils.getRoundOffMinsFromMs(program.getDurationMillis()));
+        return mContext.getResources().getQuantityString(
+                R.plurals.dvr_program_duration, durationMinutes, durationMinutes);
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/browse/RecordingCardView.java b/src/com/android/tv/dvr/ui/browse/RecordingCardView.java
new file mode 100644
index 0000000..767addc
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/RecordingCardView.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.browse;
+
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.Nullable;
+import android.support.v17.leanback.widget.BaseCardView;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.tv.R;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.ui.ViewUtils;
+import com.android.tv.util.ImageLoader;
+
+/**
+ * A CardView for displaying info about a {@link com.android.tv.dvr.data.ScheduledRecording}
+ * or {@link RecordedProgram} or {@link com.android.tv.dvr.data.SeriesRecording}.
+ */
+public class RecordingCardView extends BaseCardView {
+    // This value should be the same with
+    // android.support.v17.leanback.widget.FocusHighlightHelper.BrowseItemFocusHighlight.DURATION_MS
+    private final static int ANIMATION_DURATION = 150;
+    private final ImageView mImageView;
+    private final int mImageWidth;
+    private final int mImageHeight;
+    private String mImageUri;
+    private final TextView mMajorContentView;
+    private final TextView mMinorContentView;
+    private final ProgressBar mProgressBar;
+    private final View mAffiliatedIconContainer;
+    private final ImageView mAffiliatedIcon;
+    private final Drawable mDefaultImage;
+    private final FrameLayout mTitleArea;
+    private final TextView mFoldedTitleView;
+    private final TextView mExpandedTitleView;
+    private final ValueAnimator mExpandTitleAnimator;
+    private final int mFoldedTitleHeight;
+    private final int mExpandedTitleHeight;
+    private final boolean mExpandTitleWhenFocused;
+    private boolean mExpanded;
+    private String mDetailBackgroundImageUri;
+
+    public RecordingCardView(Context context) {
+        this(context, false);
+    }
+
+    public RecordingCardView(Context context, boolean expandTitleWhenFocused) {
+        this(context, context.getResources().getDimensionPixelSize(
+                R.dimen.dvr_library_card_image_layout_width), context.getResources()
+                .getDimensionPixelSize(R.dimen.dvr_library_card_image_layout_height),
+                expandTitleWhenFocused);
+    }
+
+    public RecordingCardView(Context context, int imageWidth, int imageHeight,
+            boolean expandTitleWhenFocused) {
+        super(context);
+        //TODO(dvr): move these to the layout XML.
+        setCardType(BaseCardView.CARD_TYPE_INFO_UNDER_WITH_EXTRA);
+        setInfoVisibility(BaseCardView.CARD_REGION_VISIBLE_ALWAYS);
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        mDefaultImage = getResources().getDrawable(R.drawable.dvr_default_poster, null);
+
+        LayoutInflater inflater = LayoutInflater.from(getContext());
+        inflater.inflate(R.layout.dvr_recording_card_view, this);
+        mImageView = (ImageView) findViewById(R.id.image);
+        mImageWidth = imageWidth;
+        mImageHeight = imageHeight;
+        mProgressBar = (ProgressBar) findViewById(R.id.recording_progress);
+        mAffiliatedIconContainer = findViewById(R.id.affiliated_icon_container);
+        mAffiliatedIcon = (ImageView) findViewById(R.id.affiliated_icon);
+        mMajorContentView = (TextView) findViewById(R.id.content_major);
+        mMinorContentView = (TextView) findViewById(R.id.content_minor);
+        mTitleArea = (FrameLayout) findViewById(R.id.title_area);
+        mFoldedTitleView = (TextView) findViewById(R.id.title_one_line);
+        mExpandedTitleView = (TextView) findViewById(R.id.title_two_lines);
+        mFoldedTitleHeight = getResources()
+                .getDimensionPixelSize(R.dimen.dvr_library_card_folded_title_height);
+        mExpandedTitleHeight = getResources()
+                .getDimensionPixelSize(R.dimen.dvr_library_card_expanded_title_height);
+        mExpandTitleAnimator = ValueAnimator.ofFloat(0.0f, 1.0f).setDuration(ANIMATION_DURATION);
+        mExpandTitleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator valueAnimator) {
+                float value = (Float) valueAnimator.getAnimatedValue();
+                mExpandedTitleView.setAlpha(value);
+                mFoldedTitleView.setAlpha(1.0f - value);
+                ViewUtils.setLayoutHeight(mTitleArea, (int) (mFoldedTitleHeight
+                        + (mExpandedTitleHeight - mFoldedTitleHeight) * value));
+            }
+        });
+        mExpandTitleWhenFocused = expandTitleWhenFocused;
+    }
+
+    @Override
+    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
+        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+        // Preload the background image going to be used in detail fragments here to prevent
+        // loading and drawing background images during activity transitions.
+        if (gainFocus) {
+            if (!TextUtils.isEmpty(mDetailBackgroundImageUri)) {
+                ImageLoader.loadBitmap(getContext(), mDetailBackgroundImageUri,
+                            Integer.MAX_VALUE, Integer.MAX_VALUE, null);
+            }
+        }
+        if (mExpandTitleWhenFocused) {
+            if (gainFocus) {
+                expandTitle(true, true);
+            } else {
+                expandTitle(false, true);
+            }
+        }
+    }
+
+    /**
+     * Expands/folds the title area to show program title with two/one lines.
+     *
+     * @param expand {@code true} to expand the title area, or {@code false} to fold it.
+     * @param withAnimation {@code true} to expand/fold with animation.
+     */
+    public void expandTitle(boolean expand, boolean withAnimation) {
+        if (expand != mExpanded && mFoldedTitleView.getLayout().getEllipsisCount(0) > 0) {
+            if (withAnimation) {
+                if (expand) {
+                    mExpandTitleAnimator.start();
+                } else {
+                    mExpandTitleAnimator.reverse();
+                }
+            } else {
+                if (expand) {
+                    mFoldedTitleView.setAlpha(0.0f);
+                    mExpandedTitleView.setAlpha(1.0f);
+                    ViewUtils.setLayoutHeight(mTitleArea, mExpandedTitleHeight);
+                } else {
+                    mFoldedTitleView.setAlpha(1.0f);
+                    mExpandedTitleView.setAlpha(0.0f);
+                    ViewUtils.setLayoutHeight(mTitleArea, mFoldedTitleHeight);
+                }
+            }
+            mExpanded = expand;
+        }
+    }
+
+    void setTitle(CharSequence title) {
+        mFoldedTitleView.setText(title);
+        mExpandedTitleView.setText(title);
+    }
+
+    void setContent(CharSequence majorContent, CharSequence minorContent) {
+        if (!TextUtils.isEmpty(majorContent)) {
+            mMajorContentView.setText(majorContent);
+            mMajorContentView.setVisibility(View.VISIBLE);
+        } else {
+            mMajorContentView.setVisibility(View.GONE);
+        }
+        if (!TextUtils.isEmpty(minorContent)) {
+            mMinorContentView.setText(minorContent);
+            mMinorContentView.setVisibility(View.VISIBLE);
+        } else {
+            mMinorContentView.setVisibility(View.GONE);
+        }
+    }
+
+    /**
+     * Sets progress bar. If progress is {@code null}, hides progress bar.
+     */
+    void setProgressBar(Integer progress) {
+        if (progress == null) {
+            mProgressBar.setVisibility(View.GONE);
+        } else {
+            mProgressBar.setProgress(progress);
+            mProgressBar.setVisibility(View.VISIBLE);
+        }
+    }
+
+    /**
+     * Sets the color of progress bar.
+     */
+    void setProgressBarColor(int color) {
+        mProgressBar.getProgressDrawable().setTint(color);
+    }
+
+    /**
+     * Sets the image URI of the poster should be shown on the card view.
+
+     * @param isChannelLogo {@code true} if the image is from channels' logo.
+     */
+    void setImageUri(String uri, boolean isChannelLogo) {
+        if (isChannelLogo) {
+            mImageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+        } else {
+            mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
+        }
+        mImageUri = uri;
+        if (TextUtils.isEmpty(uri)) {
+            mImageView.setImageDrawable(mDefaultImage);
+        } else {
+            ImageLoader.loadBitmap(getContext(), uri, mImageWidth, mImageHeight,
+                    new RecordingCardImageLoaderCallback(this, uri));
+        }
+    }
+
+    /**
+     * Sets the {@link Drawable} of the poster should be shown on the card view.
+     */
+    public void setImage(Drawable image) {
+        if (image != null) {
+            mImageView.setImageDrawable(image);
+        }
+    }
+
+    /**
+     * Sets the affiliated icon of the card view, which will be displayed at the lower-right corner
+     * of the poster.
+     */
+    public void setAffiliatedIcon(int imageResId) {
+        if (imageResId > 0) {
+            mAffiliatedIconContainer.setVisibility(View.VISIBLE);
+            mAffiliatedIcon.setImageResource(imageResId);
+        } else {
+            mAffiliatedIconContainer.setVisibility(View.INVISIBLE);
+        }
+    }
+
+    /**
+     * Sets the background image URI of the card view, which will be displayed as background when
+     * the view is clicked and shows its details fragment.
+     */
+    public void setDetailBackgroundImageUri(String uri) {
+        mDetailBackgroundImageUri = uri;
+    }
+
+    /**
+     * Returns image view.
+     */
+    public ImageView getImageView() {
+        return mImageView;
+    }
+
+    private static class RecordingCardImageLoaderCallback
+            extends ImageLoader.ImageLoaderCallback<RecordingCardView> {
+        private final String mUri;
+
+        RecordingCardImageLoaderCallback(RecordingCardView referent, String uri) {
+            super(referent);
+            mUri = uri;
+        }
+
+        @Override
+        public void onBitmapLoaded(RecordingCardView view, @Nullable Bitmap bitmap) {
+            if (bitmap == null || !mUri.equals(view.mImageUri)) {
+                view.mImageView.setImageDrawable(view.mDefaultImage);
+            } else {
+                view.mImageView.setImageDrawable(new BitmapDrawable(view.getResources(), bitmap));
+            }
+        }
+    }
+
+    public void reset() {
+        mFoldedTitleView.setText(null);
+        mExpandedTitleView.setText(null);
+        setContent(null, null);
+        mImageView.setImageDrawable(mDefaultImage);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
new file mode 100644
index 0000000..56ec357
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/RecordingDetailsFragment.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.browse;
+
+import android.os.Bundle;
+import android.support.v17.leanback.app.DetailsFragment;
+
+import com.android.tv.TvApplication;
+import com.android.tv.dvr.data.ScheduledRecording;
+
+/**
+ * {@link DetailsFragment} for recordings in DVR.
+ */
+abstract class RecordingDetailsFragment extends DvrDetailsFragment {
+    private ScheduledRecording mRecording;
+
+    @Override
+    protected void onCreateInternal() {
+        setDetailsOverviewRow(DetailsContent
+                .createFromScheduledRecording(getContext(), mRecording));
+    }
+
+    @Override
+    protected boolean onLoadRecordingDetails(Bundle args) {
+        long scheduledRecordingId = args.getLong(DvrDetailsActivity.RECORDING_ID);
+        mRecording = TvApplication.getSingletons(getContext()).getDvrDataManager()
+                .getScheduledRecording(scheduledRecordingId);
+        return mRecording != null;
+    }
+
+    /**
+     * Returns {@link ScheduledRecording} for the current fragment.
+     */
+    public ScheduledRecording getRecording() {
+        return mRecording;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/ScheduledRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
similarity index 95%
rename from src/com/android/tv/dvr/ui/ScheduledRecordingDetailsFragment.java
rename to src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
index 60816bb..958f8bf 100644
--- a/src/com/android/tv/dvr/ui/ScheduledRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingDetailsFragment.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.content.res.Resources;
 import android.os.Bundle;
@@ -26,7 +26,7 @@
 import com.android.tv.R;
 import com.android.tv.TvApplication;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
+import com.android.tv.dvr.ui.DvrUiHelper;
 
 /**
  * {@link RecordingDetailsFragment} for scheduled recording in DVR.
@@ -66,7 +66,7 @@
             adapter.set(ACTION_VIEW_SCHEDULE, mScheduleAction);
         }
         adapter.set(ACTION_CANCEL, new Action(ACTION_CANCEL,
-                res.getString(R.string.epg_dvr_dialog_message_remove_recording_schedule), null,
+                res.getString(R.string.dvr_detail_cancel_recording), null,
                 res.getDrawable(R.drawable.ic_dvr_cancel_32dp)));
         return adapter;
     }
diff --git a/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java
new file mode 100644
index 0000000..273d3d1
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/browse/ScheduledRecordingPresenter.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.browse;
+
+import android.content.Context;
+import android.os.Handler;
+
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.util.Utils;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Presents a {@link ScheduledRecording} in the {@link DvrBrowseFragment}.
+ */
+class ScheduledRecordingPresenter extends DvrItemPresenter<ScheduledRecording> {
+    private static final long PROGRESS_UPDATE_INTERVAL_MS = TimeUnit.SECONDS.toMillis(5);
+
+    private final DvrManager mDvrManager;
+    private final int mProgressBarColor;
+
+    private final class ScheduledRecordingViewHolder extends DvrItemViewHolder {
+        private final Handler mHandler = new Handler();
+        private ScheduledRecording mScheduledRecording;
+        private final Runnable mProgressBarUpdater = new Runnable() {
+            @Override
+            public void run() {
+                updateProgressBar();
+                mHandler.postDelayed(this, PROGRESS_UPDATE_INTERVAL_MS);
+            }
+        };
+
+        ScheduledRecordingViewHolder(RecordingCardView view, int progressBarColor) {
+            super(view);
+            view.setProgressBarColor(progressBarColor);
+        }
+
+        @Override
+        protected void onBound(ScheduledRecording recording) {
+            mScheduledRecording = recording;
+            updateProgressBar();
+            startUpdateProgressBar();
+        }
+
+        @Override
+        protected void onUnbound() {
+            stopUpdateProgressBar();
+            mScheduledRecording = null;
+            getView().reset();
+        }
+
+        private void updateProgressBar() {
+            if (mScheduledRecording == null) {
+                return;
+            }
+            int recordingState = mScheduledRecording.getState();
+            RecordingCardView cardView = (RecordingCardView) view;
+            if (recordingState == ScheduledRecording.STATE_RECORDING_IN_PROGRESS) {
+                cardView.setProgressBar(Math.max(0, Math.min((int) (100 *
+                        (System.currentTimeMillis() - mScheduledRecording.getStartTimeMs())
+                        / mScheduledRecording.getDuration()), 100)));
+            } else if (recordingState == ScheduledRecording.STATE_RECORDING_FINISHED) {
+                cardView.setProgressBar(100);
+            } else {
+                // Hides progress bar.
+                cardView.setProgressBar(null);
+            }
+        }
+
+        private void startUpdateProgressBar() {
+            mHandler.post(mProgressBarUpdater);
+        }
+
+        private void stopUpdateProgressBar() {
+            mHandler.removeCallbacks(mProgressBarUpdater);
+        }
+    }
+
+    public ScheduledRecordingPresenter(Context context) {
+        super(context);
+        mDvrManager = TvApplication.getSingletons(mContext).getDvrManager();
+        mProgressBarColor = mContext.getResources()
+                .getColor(R.color.play_controls_recording_icon_color_on_focus);
+    }
+
+    @Override
+    public DvrItemViewHolder onCreateDvrItemViewHolder() {
+        return new ScheduledRecordingViewHolder(new RecordingCardView(mContext), mProgressBarColor);
+    }
+
+    @Override
+    public void onBindDvrItemViewHolder(DvrItemViewHolder baseHolder,
+            ScheduledRecording recording) {
+        final ScheduledRecordingViewHolder viewHolder = (ScheduledRecordingViewHolder) baseHolder;
+        final RecordingCardView cardView = viewHolder.getView();
+        DetailsContent details = DetailsContent.createFromScheduledRecording(mContext, recording);
+        cardView.setTitle(details.getTitle());
+        cardView.setImageUri(details.getLogoImageUri(), details.isUsingChannelLogo());
+        cardView.setAffiliatedIcon(mDvrManager.isConflicting(recording) ?
+                R.drawable.ic_warning_white_32dp : 0);
+        cardView.setContent(generateMajorContent(recording), null);
+        cardView.setDetailBackgroundImageUri(details.getBackgroundImageUri());
+    }
+
+    private String generateMajorContent(ScheduledRecording recording) {
+        int dateDifference = Utils.computeDateDifference(System.currentTimeMillis(),
+                recording.getStartTimeMs());
+        if (dateDifference <= 0) {
+            return mContext.getString(R.string.dvr_date_today_time,
+                    Utils.getDurationString(mContext, recording.getStartTimeMs(),
+                            recording.getEndTimeMs(), false, false, true, 0));
+        } else if (dateDifference == 1) {
+            return mContext.getString(R.string.dvr_date_tomorrow_time,
+                    Utils.getDurationString(mContext, recording.getStartTimeMs(),
+                            recording.getEndTimeMs(), false, false, true, 0));
+        } else {
+            return Utils.getDurationString(mContext, recording.getStartTimeMs(),
+                    recording.getStartTimeMs(), false, true, false, 0);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/SeriesRecordingDetailsFragment.java b/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
similarity index 90%
rename from src/com/android/tv/dvr/ui/SeriesRecordingDetailsFragment.java
rename to src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
index e9e391d..c2aa8e9 100644
--- a/src/com/android/tv/dvr/ui/SeriesRecordingDetailsFragment.java
+++ b/src/com/android/tv/dvr/ui/browse/SeriesRecordingDetailsFragment.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
 import android.content.res.Resources;
 import android.graphics.drawable.Drawable;
@@ -28,7 +28,6 @@
 import android.support.v17.leanback.widget.DetailsOverviewRowPresenter;
 import android.support.v17.leanback.widget.HeaderItem;
 import android.support.v17.leanback.widget.ListRow;
-import android.support.v17.leanback.widget.ListRowPresenter;
 import android.support.v17.leanback.widget.OnActionClickedListener;
 import android.support.v17.leanback.widget.PresenterSelector;
 import android.support.v17.leanback.widget.SparseArrayObjectAdapter;
@@ -37,14 +36,12 @@
 import com.android.tv.R;
 import com.android.tv.TvApplication;
 import com.android.tv.data.BaseProgram;
-import com.android.tv.data.Channel;
 import com.android.tv.dvr.DvrDataManager;
-import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
 import com.android.tv.dvr.DvrWatchedPositionManager;
-import com.android.tv.dvr.RecordedProgram;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.ui.DvrUiHelper;
+import com.android.tv.dvr.ui.SortedArrayAdapter;
 
 import java.util.Collections;
 import java.util.Comparator;
@@ -67,7 +64,6 @@
     // After fragments are created, it should be cleared to save resources.
     private List<RecordedProgram> mRecordedPrograms;
     private RecordedProgram mRecommendRecordedProgram;
-    private DetailsContent mDetailsContent;
     private int mSeasonRowCount;
     private SparseArrayObjectAdapter mActionsAdapter;
     private Action mDeleteAction;
@@ -85,7 +81,7 @@
         mWatchLabel = getString(R.string.dvr_detail_watch);
         mResumeLabel = getString(R.string.dvr_detail_series_resume);
         mWatchDrawable = getResources().getDrawable(R.drawable.lb_ic_play, null);
-        mRecordedProgramPresenter = new RecordedProgramPresenter(getContext(), true);
+        mRecordedProgramPresenter = new RecordedProgramPresenter(getContext(), true, true);
         super.onCreate(savedInstanceState);
     }
 
@@ -93,7 +89,7 @@
     protected void onCreateInternal() {
         mDvrWatchedPositionManager = TvApplication.getSingletons(getActivity())
                 .getDvrWatchedPositionManager();
-        setDetailsOverviewRow(mDetailsContent);
+        setDetailsOverviewRow(DetailsContent.createFromSeriesRecording(getContext(), mSeries));
         setupRecordedProgramsRow();
         mDvrDataManager.addSeriesRecordingListener(this);
         mDvrDataManager.addRecordedProgramListener(this);
@@ -149,7 +145,6 @@
         }
         mRecordedPrograms = mDvrDataManager.getRecordedPrograms(mSeries.getId());
         Collections.sort(mRecordedPrograms, RecordedProgram.SEASON_REVERSED_EPISODE_COMPARATOR);
-        mDetailsContent = createDetailsContent();
         return true;
     }
 
@@ -158,22 +153,10 @@
             DetailsOverviewRowPresenter rowPresenter) {
         ClassPresenterSelector presenterSelector = new ClassPresenterSelector();
         presenterSelector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
-        presenterSelector.addClassPresenter(ListRow.class, new ListRowPresenter());
+        presenterSelector.addClassPresenter(ListRow.class, new DvrListRowPresenter(getContext()));
         return presenterSelector;
     }
 
-    private DetailsContent createDetailsContent() {
-        Channel channel = TvApplication.getSingletons(getContext()).getChannelDataManager()
-                .getChannel(mSeries.getChannelId());
-        String description = TextUtils.isEmpty(mSeries.getLongDescription())
-                ? mSeries.getDescription() : mSeries.getLongDescription();
-        return new DetailsContent.Builder()
-                .setTitle(mSeries.getTitle())
-                .setDescription(description)
-                .setImageUris(mSeries.getPosterUri(), mSeries.getPhotoUri(), channel)
-                .build();
-    }
-
     @Override
     protected SparseArrayObjectAdapter onCreateActionsAdapter() {
         mActionsAdapter = new SparseArrayObjectAdapter(new ActionPresenterSelector());
@@ -203,10 +186,7 @@
         mDvrDataManager.removeSeriesRecordingListener(this);
         mDvrDataManager.removeRecordedProgramListener(this);
         if (mSeries != null) {
-            DvrManager dvrManager = TvApplication.getSingletons(getActivity()).getDvrManager();
-            if (dvrManager.canRemoveSeriesRecording(mSeries.getId())) {
-                dvrManager.removeSeriesRecording(mSeries.getId());
-            }
+            mDvrDataManager.checkAndRemoveEmptySeriesRecording(mSeries.getId());
         }
         mRecordedProgramPresenter.unbindAllViewHolders();
     }
@@ -265,7 +245,6 @@
     public void onSeriesRecordingRemoved(SeriesRecording... seriesRecordings) {
         for (SeriesRecording series : seriesRecordings) {
             if (series.getId() == mSeries.getId()) {
-                mSeries = null;
                 getActivity().finish();
                 return;
             }
@@ -372,4 +351,4 @@
             return program.getId();
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/SeriesRecordingPresenter.java b/src/com/android/tv/dvr/ui/browse/SeriesRecordingPresenter.java
similarity index 79%
rename from src/com/android/tv/dvr/ui/SeriesRecordingPresenter.java
rename to src/com/android/tv/dvr/ui/browse/SeriesRecordingPresenter.java
index c2c0f59..e508259 100644
--- a/src/com/android/tv/dvr/ui/SeriesRecordingPresenter.java
+++ b/src/com/android/tv/dvr/ui/browse/SeriesRecordingPresenter.java
@@ -14,42 +14,36 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.browse;
 
-import android.app.Activity;
 import android.content.Context;
-import android.media.tv.TvContract;
 import android.media.tv.TvInputManager;
 import android.text.TextUtils;
-import android.view.ViewGroup;
 
 import com.android.tv.ApplicationSingletons;
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.data.Channel;
-import com.android.tv.data.ChannelDataManager;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.RecordedProgramListener;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.DvrWatchedPositionManager;
 import com.android.tv.dvr.DvrWatchedPositionManager.WatchedPositionChangedListener;
-import com.android.tv.dvr.RecordedProgram;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 
 import java.util.List;
 
 /**
  * Presents a {@link SeriesRecording} in {@link DvrBrowseFragment}.
  */
-public class SeriesRecordingPresenter extends DvrItemPresenter {
-    private final ChannelDataManager mChannelDataManager;
+class SeriesRecordingPresenter extends DvrItemPresenter<SeriesRecording> {
     private final DvrDataManager mDvrDataManager;
     private final DvrManager mDvrManager;
     private final DvrWatchedPositionManager mWatchedPositionManager;
 
-    private static final class SeriesRecordingViewHolder extends ViewHolder implements
+    private final class SeriesRecordingViewHolder extends DvrItemViewHolder implements
             WatchedPositionChangedListener, ScheduledRecordingListener, RecordedProgramListener {
         private SeriesRecording mSeriesRecording;
         private RecordingCardView mCardView;
@@ -138,7 +132,8 @@
             // Do nothing
         }
 
-        public void onBound(SeriesRecording seriesRecording) {
+        @Override
+        protected void onBound(SeriesRecording seriesRecording) {
             mSeriesRecording = seriesRecording;
             mDvrDataManager.addScheduledRecordingListener(this);
             mDvrDataManager.addRecordedProgramListener(this);
@@ -152,10 +147,12 @@
             updateCardViewContent();
         }
 
-        public void onUnbound() {
+        @Override
+        protected void onUnbound() {
             mDvrDataManager.removeScheduledRecordingListener(this);
             mDvrDataManager.removeRecordedProgramListener(this);
             mWatchedPositionManager.removeListener(this);
+            getView().reset();
         }
 
         private void updateCardViewContent() {
@@ -186,29 +183,28 @@
     }
 
     public SeriesRecordingPresenter(Context context) {
+        super(context);
         ApplicationSingletons singletons = TvApplication.getSingletons(context);
-        mChannelDataManager = singletons.getChannelDataManager();
         mDvrDataManager = singletons.getDvrDataManager();
         mDvrManager = singletons.getDvrManager();
         mWatchedPositionManager = singletons.getDvrWatchedPositionManager();
     }
 
     @Override
-    public ViewHolder onCreateViewHolder(ViewGroup parent) {
-        Context context = parent.getContext();
-        RecordingCardView view = new RecordingCardView(context);
-        return new SeriesRecordingViewHolder(view, mDvrDataManager, mDvrManager,
-                mWatchedPositionManager);
+    public DvrItemViewHolder onCreateDvrItemViewHolder() {
+        return new SeriesRecordingViewHolder(new RecordingCardView(mContext), mDvrDataManager,
+                mDvrManager, mWatchedPositionManager);
     }
 
     @Override
-    public void onBindViewHolder(ViewHolder baseHolder, Object o) {
+    public void onBindDvrItemViewHolder(DvrItemViewHolder baseHolder, SeriesRecording series) {
         final SeriesRecordingViewHolder viewHolder = (SeriesRecordingViewHolder) baseHolder;
-        final SeriesRecording seriesRecording = (SeriesRecording) o;
-        final RecordingCardView cardView = (RecordingCardView) viewHolder.view;
-        viewHolder.onBound(seriesRecording);
-        setTitleAndImage(cardView, seriesRecording);
-        super.onBindViewHolder(baseHolder, o);
+        final RecordingCardView cardView = viewHolder.getView();
+        viewHolder.onBound(series);
+        DetailsContent details = DetailsContent.createFromSeriesRecording(mContext, series);
+        cardView.setTitle(details.getTitle());
+        cardView.setImageUri(details.getLogoImageUri(), details.isUsingChannelLogo());
+        cardView.setDetailBackgroundImageUri(details.getBackgroundImageUri());
     }
 
     @Override
@@ -217,18 +213,4 @@
         ((SeriesRecordingViewHolder) viewHolder).onUnbound();
         super.onUnbindViewHolder(viewHolder);
     }
-
-    private void setTitleAndImage(RecordingCardView cardView, SeriesRecording recording) {
-        cardView.setTitle(recording.getTitle());
-        if (recording.getPosterUri() != null) {
-            cardView.setImageUri(recording.getPosterUri(), false);
-        } else {
-            Channel channel = mChannelDataManager.getChannel(recording.getChannelId());
-            String imageUri = null;
-            if (channel != null) {
-                imageUri = TvContract.buildChannelLogoUri(channel.getId()).toString();
-            }
-            cardView.setImageUri(imageUri, true);
-        }
-    }
 }
diff --git a/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java b/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
index d28f026..b9407b1 100644
--- a/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/BaseDvrSchedulesFragment.java
@@ -29,7 +29,7 @@
 import com.android.tv.TvApplication;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrScheduleManager;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 
 /**
  * A  base fragment to show the list of schedule recordings.
@@ -40,7 +40,8 @@
     /**
      * The key for scheduled recording which has be selected in the list.
      */
-    public static String SCHEDULES_KEY_SCHEDULED_RECORDING = "schedules_key_scheduled_recording";
+    public static final String SCHEDULES_KEY_SCHEDULED_RECORDING =
+            "schedules_key_scheduled_recording";
 
     private ScheduleRowAdapter mRowsAdapter;
     private TextView mEmptyInfoScreenView;
diff --git a/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java b/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java
new file mode 100644
index 0000000..a0410bb
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/list/DvrSchedulesActivity.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.list;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.os.Bundle;
+import android.support.annotation.IntDef;
+
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.data.Program;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
+import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
+import com.android.tv.dvr.ui.BigArguments;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Activity to show the list of recording schedules.
+ */
+public class DvrSchedulesActivity extends Activity {
+    /**
+     * The key for the type of the schedules which will be listed in the list. The type of the value
+     * should be {@link ScheduleListType}.
+     */
+    public static final String KEY_SCHEDULES_TYPE = "schedules_type";
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({TYPE_FULL_SCHEDULE, TYPE_SERIES_SCHEDULE})
+    public @interface ScheduleListType {}
+    /**
+     * A type which means the activity will display the full scheduled recordings.
+     */
+    public static final int TYPE_FULL_SCHEDULE = 0;
+    /**
+     * A type which means the activity will display a scheduled recording list of a series
+     * recording.
+     */
+    public static final int TYPE_SERIES_SCHEDULE = 1;
+
+    @Override
+    public void onCreate(final Bundle savedInstanceState) {
+        TvApplication.setCurrentRunningProcess(this, true);
+        // Pass null to prevent automatically re-creating fragments
+        super.onCreate(null);
+        setContentView(R.layout.activity_dvr_schedules);
+        int scheduleType = getIntent().getIntExtra(KEY_SCHEDULES_TYPE, TYPE_FULL_SCHEDULE);
+        if (scheduleType == TYPE_FULL_SCHEDULE) {
+            DvrSchedulesFragment schedulesFragment = new DvrSchedulesFragment();
+            schedulesFragment.setArguments(getIntent().getExtras());
+            getFragmentManager().beginTransaction().add(
+                    R.id.fragment_container, schedulesFragment).commit();
+        } else if (scheduleType == TYPE_SERIES_SCHEDULE) {
+            if (BigArguments.getArgument(DvrSeriesSchedulesFragment
+                    .SERIES_SCHEDULES_KEY_SERIES_PROGRAMS) != null) {
+                // The programs will be passed to the DvrSeriesSchedulesFragment, so don't need
+                // to reset the BigArguments.
+                showDvrSeriesSchedulesFragment(getIntent().getExtras());
+            } else {
+                final ProgressDialog dialog = ProgressDialog.show(this, null, getString(
+                        R.string.dvr_series_progress_message_reading_programs));
+                SeriesRecording seriesRecording = getIntent().getExtras()
+                        .getParcelable(DvrSeriesSchedulesFragment
+                                .SERIES_SCHEDULES_KEY_SERIES_RECORDING);
+                // To get programs faster, hold the update of the series schedules.
+                SeriesRecordingScheduler.getInstance(this).pauseUpdate();
+                new EpisodicProgramLoadTask(this, Collections.singletonList(seriesRecording)) {
+                    @Override
+                    protected void onPostExecute(List<Program> programs) {
+                        SeriesRecordingScheduler.getInstance(DvrSchedulesActivity.this)
+                                .resumeUpdate();
+                        dialog.dismiss();
+                        Bundle args = getIntent().getExtras();
+                        BigArguments.reset();
+                        BigArguments.setArgument(
+                                DvrSeriesSchedulesFragment.SERIES_SCHEDULES_KEY_SERIES_PROGRAMS,
+                                programs == null ? Collections.EMPTY_LIST : programs);
+                        showDvrSeriesSchedulesFragment(args);
+                    }
+                }.setLoadCurrentProgram(true)
+                        .setLoadDisallowedProgram(true)
+                        .setLoadScheduledEpisode(true)
+                        .setIgnoreChannelOption(true)
+                        .execute();
+            }
+        } else {
+            finish();
+        }
+    }
+
+    private void showDvrSeriesSchedulesFragment(Bundle args) {
+        DvrSeriesSchedulesFragment schedulesFragment = new DvrSeriesSchedulesFragment();
+        schedulesFragment.setArguments(args);
+        getFragmentManager().beginTransaction().add(
+                R.id.fragment_container, schedulesFragment).commit();
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java b/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
index 722c9b6..3cbb500 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSchedulesFragment.java
@@ -18,12 +18,9 @@
 
 import android.os.Bundle;
 import android.support.v17.leanback.widget.ClassPresenterSelector;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
 
 import com.android.tv.R;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.ui.list.SchedulesHeaderRowPresenter.DateHeaderRowPresenter;
 
 /**
diff --git a/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java b/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java
index 42a1e72..57e7a88 100644
--- a/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java
+++ b/src/com/android/tv/dvr/ui/list/DvrSeriesSchedulesFragment.java
@@ -17,6 +17,7 @@
 package com.android.tv.dvr.ui.list;
 
 import android.annotation.TargetApi;
+import android.content.Context;
 import android.database.ContentObserver;
 import android.media.tv.TvContract.Programs;
 import android.net.Uri;
@@ -35,11 +36,13 @@
 import com.android.tv.TvApplication;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.Program;
+import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.SeriesRecordingListener;
-import com.android.tv.dvr.EpisodicProgramLoadTask;
-import com.android.tv.dvr.SeriesRecording;
-import com.android.tv.dvr.ui.list.SchedulesHeaderRowPresenter.SeriesRecordingHeaderRowPresenter;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.provider.EpisodicProgramLoadTask;
+import com.android.tv.dvr.ui.BigArguments;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -47,20 +50,22 @@
  */
 @TargetApi(Build.VERSION_CODES.N)
 public class DvrSeriesSchedulesFragment extends BaseDvrSchedulesFragment {
-    private static final String TAG = "DvrSeriesSchedulesFragment";
     /**
      * The key for series recording whose scheduled recording list will be displayed.
+     * Type: {@link SeriesRecording}
      */
     public static final String SERIES_SCHEDULES_KEY_SERIES_RECORDING =
             "series_schedules_key_series_recording";
     /**
-     * The key for programs belong to the series recording whose scheduled recording
-     * list will be displayed.
+     * The key for programs which belong to the series recording whose scheduled recording list
+     * will be displayed.
+     * Type: List<{@link Program}>
      */
     public static final String SERIES_SCHEDULES_KEY_SERIES_PROGRAMS =
             "series_schedules_key_series_programs";
 
     private ChannelDataManager mChannelDataManager;
+    private DvrDataManager mDvrDataManager;
     private SeriesRecording mSeriesRecording;
     private List<Program> mPrograms;
     private EpisodicProgramLoadTask mProgramLoadTask;
@@ -87,20 +92,22 @@
                                 && getRowsAdapter() instanceof SeriesScheduleRowAdapter) {
                             ((SeriesScheduleRowAdapter) getRowsAdapter())
                                     .onSeriesRecordingUpdated(r);
+                            mSeriesRecording = r;
+                            updateEmptyMessage();
                             return;
                         }
                     }
                 }
             };
 
-    private final ContentObserver mContentObserver =
-            new ContentObserver(new Handler(Looper.getMainLooper())) {
-                @Override
-                public void onChange(boolean selfChange, Uri uri) {
-                    super.onChange(selfChange, uri);
-                    executeProgramLoadingTask();
-                }
-            };
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+    private final ContentObserver mContentObserver = new ContentObserver(mHandler) {
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            super.onChange(selfChange, uri);
+            executeProgramLoadingTask();
+        }
+    };
 
     private final ChannelDataManager.Listener mChannelListener = new ChannelDataManager.Listener() {
         @Override
@@ -120,17 +127,28 @@
     }
 
     @Override
-    public void onCreate(Bundle savedInstanceState) {
+    public void onAttach(Context context) {
+        super.onAttach(context);
         Bundle args = getArguments();
         if (args != null) {
             mSeriesRecording = args.getParcelable(SERIES_SCHEDULES_KEY_SERIES_RECORDING);
-            mPrograms = args.getParcelableArrayList(SERIES_SCHEDULES_KEY_SERIES_PROGRAMS);
+            mPrograms = (List<Program>) BigArguments.getArgument(
+                    SERIES_SCHEDULES_KEY_SERIES_PROGRAMS);
+            BigArguments.reset();
         }
+        if (args == null || mPrograms == null) {
+            getActivity().finish();
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         ApplicationSingletons singletons = TvApplication.getSingletons(getContext());
-        singletons.getDvrDataManager().addSeriesRecordingListener(mSeriesRecordingListener);
         mChannelDataManager = singletons.getChannelDataManager();
         mChannelDataManager.addListener(mChannelListener);
+        mDvrDataManager = singletons.getDvrDataManager();
+        mDvrDataManager.addSeriesRecordingListener(mSeriesRecordingListener);
         getContext().getContentResolver().registerContentObserver(Programs.CONTENT_URI, true,
                 mContentObserver);
     }
@@ -144,8 +162,16 @@
 
     private void onProgramsUpdated() {
         ((SeriesScheduleRowAdapter) getRowsAdapter()).setPrograms(mPrograms);
+        updateEmptyMessage();
+    }
+
+    private void updateEmptyMessage() {
         if (mPrograms == null || mPrograms.isEmpty()) {
-            showEmptyMessage(R.string.dvr_series_schedules_empty_state);
+            if (mSeriesRecording.getState() == SeriesRecording.STATE_SERIES_STOPPED) {
+                showEmptyMessage(R.string.dvr_series_schedules_stopped_empty_state);
+            } else {
+                showEmptyMessage(R.string.dvr_series_schedules_empty_state);
+            }
         } else {
             hideEmptyMessage();
         }
@@ -158,15 +184,15 @@
             mProgramLoadTask = null;
         }
         getContext().getContentResolver().unregisterContentObserver(mContentObserver);
+        mHandler.removeCallbacksAndMessages(null);
         mChannelDataManager.removeListener(mChannelListener);
-        TvApplication.getSingletons(getContext()).getDvrDataManager()
-                .removeSeriesRecordingListener(mSeriesRecordingListener);
+        mDvrDataManager.removeSeriesRecordingListener(mSeriesRecordingListener);
         super.onDestroy();
     }
 
     @Override
     public SchedulesHeaderRowPresenter onCreateHeaderRowPresenter() {
-        return new SeriesRecordingHeaderRowPresenter(getContext());
+        return new SchedulesHeaderRowPresenter.SeriesRecordingHeaderRowPresenter(getContext());
     }
 
     @Override
@@ -195,7 +221,7 @@
         mProgramLoadTask = new EpisodicProgramLoadTask(getContext(), mSeriesRecording) {
             @Override
             protected void onPostExecute(List<Program> programs) {
-                mPrograms = programs;
+                mPrograms = programs == null ? Collections.EMPTY_LIST : programs;
                 onProgramsUpdated();
             }
         };
@@ -205,4 +231,4 @@
                 .setIgnoreChannelOption(true)
                 .execute();
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java b/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
index 23aebf5..2af832e 100644
--- a/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
+++ b/src/com/android/tv/dvr/ui/list/EpisodicProgramRow.java
@@ -19,13 +19,14 @@
 import android.content.Context;
 
 import com.android.tv.data.Program;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.ScheduledRecording.Builder;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording.Builder;
+import com.android.tv.dvr.ui.DvrUiHelper;
 
 /**
  * A class for the episodic program.
  */
-public class EpisodicProgramRow extends ScheduleRow {
+class EpisodicProgramRow extends ScheduleRow {
     private final String mInputId;
     private final Program mProgram;
 
@@ -65,7 +66,7 @@
 
     @Override
     public String getProgramTitleWithEpisodeNumber(Context context) {
-        return mProgram.getTitleWithEpisodeNumber(context);
+        return DvrUiHelper.getStyledTitleWithEpisodeNumber(context, mProgram, 0).toString();
     }
 
     @Override
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRow.java b/src/com/android/tv/dvr/ui/list/ScheduleRow.java
index 3fc92e8..91ba393 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRow.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRow.java
@@ -20,12 +20,13 @@
 import android.support.annotation.Nullable;
 
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.ui.DvrUiHelper;
 
 /**
  * A class for schedule recording row.
  */
-public class ScheduleRow {
+class ScheduleRow {
     private final SchedulesHeaderRow mHeaderRow;
     @Nullable private ScheduledRecording mSchedule;
     private boolean mStopRecordingRequested;
@@ -166,7 +167,8 @@
      * Returns the program title with episode number.
      */
     public String getProgramTitleWithEpisodeNumber(Context context) {
-        return mSchedule != null ? mSchedule.getProgramTitleWithEpisodeNumber(context) : null;
+        return mSchedule != null ? DvrUiHelper.getStyledTitleWithEpisodeNumber(context,
+                mSchedule, 0).toString() : null;
     }
 
     /**
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java b/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
index 9cc8265..97d6047 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRowAdapter.java
@@ -30,8 +30,8 @@
 import com.android.tv.TvApplication;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ScheduledRecording;
 import com.android.tv.dvr.ui.list.SchedulesHeaderRow.DateHeaderRow;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.util.Utils;
 
 import java.util.ArrayList;
@@ -43,7 +43,7 @@
 /**
  * An adapter for {@link ScheduleRow}.
  */
-public class ScheduleRowAdapter extends ArrayObjectAdapter {
+class ScheduleRowAdapter extends ArrayObjectAdapter {
     private static final String TAG = "ScheduleRowAdapter";
     private static final boolean DEBUG = false;
 
diff --git a/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java b/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
index 1257e72..dc4e3c4 100644
--- a/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/ScheduleRowPresenter.java
@@ -42,25 +42,24 @@
 import com.android.tv.TvApplication;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
+import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dvr.DvrManager;
 import com.android.tv.dvr.DvrScheduleManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.ui.DvrStopRecordingFragment;
-import com.android.tv.dvr.ui.HalfSizedDialogFragment;
+import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.util.ToastUtils;
 import com.android.tv.util.Utils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.List;
-import java.util.concurrent.TimeUnit;
 
 /**
  * A RowPresenter for {@link ScheduleRow}.
  */
 @TargetApi(Build.VERSION_CODES.N)
-public class ScheduleRowPresenter extends RowPresenter {
+class ScheduleRowPresenter extends RowPresenter {
     private static final String TAG = "ScheduleRowPresenter";
 
     @Retention(RetentionPolicy.SOURCE)
@@ -345,7 +344,9 @@
         viewHolder.mInfoContainer.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View view) {
-                onInfoClicked(row);
+                if (isInfoClickable(row)) {
+                    onInfoClicked(row);
+                }
             }
         });
 
@@ -366,8 +367,7 @@
         viewHolder.mTimeView.setText(onGetRecordingTimeText(row));
         String programInfoText = onGetProgramInfoText(row);
         if (TextUtils.isEmpty(programInfoText)) {
-            int durationMins =
-                    Math.max((int) TimeUnit.MILLISECONDS.toMinutes(row.getDuration()), 1);
+            int durationMins = Math.max(1, Utils.getRoundOffMinsFromMs(row.getDuration()));
             programInfoText = mContext.getResources().getQuantityString(
                     R.plurals.dvr_schedules_recording_duration, durationMins, durationMins);
         }
@@ -403,6 +403,7 @@
         } else {
             viewHolder.whiteBackInfo();
         }
+        viewHolder.mInfoContainer.setFocusable(isInfoClickable(row));
         updateActionContainer(viewHolder, viewHolder.isSelected());
     }
 
@@ -454,11 +455,13 @@
     /**
      * Called when user click Info in {@link ScheduleRow}.
      */
-    protected void onInfoClicked(ScheduleRow scheduleRow) {
-        ScheduledRecording schedule = scheduleRow.getSchedule();
-        if (schedule != null) {
-            DvrUiHelper.startDetailsActivity((Activity) mContext, schedule, null, true);
-        }
+    protected void onInfoClicked(ScheduleRow row) {
+        DvrUiHelper.startDetailsActivity((Activity) mContext, row.getSchedule(), null, true);
+    }
+
+    private boolean isInfoClickable(ScheduleRow row) {
+        return row.getSchedule() != null
+                && (row.getSchedule().isNotStarted() || row.getSchedule().isInProgress());
     }
 
     /**
@@ -545,7 +548,7 @@
             // This row has been deleted.
             return;
         }
-        if (row.isOnAir() && row.isRecordingInProgress() && !row.isStopRecordingRequested()) {
+        if (row.isRecordingInProgress() && !row.isStopRecordingRequested()) {
             row.setStopRecordingRequested(true);
             mDvrManager.stopRecording(row.getSchedule());
             CharSequence deletedInfo = onGetProgramInfoText(row);
@@ -670,10 +673,9 @@
                             hideActionView(viewHolder.mFirstActionContainer, View.GONE);
                         }
                     };
-                    if (mLastFocusedViewId == R.id.action_first_container
-                            || mLastFocusedViewId == R.id.action_second_container) {
-                        mLastFocusedViewId = R.id.info_container;
-                    }
+                    mLastFocusedViewId = R.id.info_container;
+                    SoftPreconditions.checkState(viewHolder.mInfoContainer.isFocusable(), TAG,
+                            "No focusable view in this row: " + viewHolder);
                     break;
             }
             View view = viewHolder.view.findViewById(mLastFocusedViewId);
@@ -683,8 +685,10 @@
                 // requestFocus() explicitly.
                 if (view.hasFocus()) {
                     viewHolder.mPendingAnimationRunnable.run();
-                } else {
+                } else if (view.isFocusable()){
                     view.requestFocus();
+                } else {
+                    viewHolder.view.requestFocus();
                 }
             }
         } else {
@@ -737,10 +741,10 @@
     @ScheduleRowAction
     protected int[] getAvailableActions(ScheduleRow row) {
         if (row.getSchedule() != null) {
-            if (row.isOnAir()) {
-                if (row.isRecordingInProgress()) {
-                    return new int[] {ACTION_STOP_RECORDING};
-                } else if (row.isRecordingNotStarted()) {
+            if (row.isRecordingInProgress()) {
+                return new int[]{ACTION_STOP_RECORDING};
+            } else if (row.isOnAir()) {
+                if (row.isRecordingNotStarted()) {
                     if (canResolveConflict()) {
                         // The "START" action can change the conflict states.
                         return new int[] {ACTION_REMOVE_SCHEDULE, ACTION_START_RECORDING};
diff --git a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
index 0fb0924..715ecb8 100644
--- a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
+++ b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRow.java
@@ -16,12 +16,15 @@
 
 package com.android.tv.dvr.ui.list;
 
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.data.Program;
+import com.android.tv.dvr.data.SeriesRecording;
+
+import java.util.List;
 
 /**
  * A base class for the rows for schedules' header.
  */
-public abstract class SchedulesHeaderRow {
+abstract class SchedulesHeaderRow {
     private String mTitle;
     private String mDescription;
     private int mItemCount;
@@ -98,11 +101,20 @@
      */
     public static class SeriesRecordingHeaderRow extends SchedulesHeaderRow {
         private SeriesRecording mSeriesRecording;
+        private List<Program> mPrograms;
 
         public SeriesRecordingHeaderRow(String title, String description, int itemCount,
-                SeriesRecording series) {
+                SeriesRecording series, List<Program> programs) {
             super(title, description, itemCount);
             mSeriesRecording = series;
+            mPrograms = programs;
+        }
+
+        /**
+         * Returns the list of programs which belong to the series.
+         */
+        public List<Program> getPrograms() {
+            return mPrograms;
         }
 
         /**
@@ -119,4 +131,4 @@
             mSeriesRecording = seriesRecording;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
index 69c33a9..fe2033b 100644
--- a/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/SchedulesHeaderRowPresenter.java
@@ -30,15 +30,14 @@
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.SeriesRecording;
-import com.android.tv.dvr.ui.DvrSchedulesActivity;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.dvr.ui.list.SchedulesHeaderRow.SeriesRecordingHeaderRow;
 
 /**
  * A base class for RowPresenter for {@link SchedulesHeaderRow}
  */
-public abstract class SchedulesHeaderRowPresenter extends RowPresenter {
+abstract class SchedulesHeaderRowPresenter extends RowPresenter {
     private Context mContext;
 
     public SchedulesHeaderRowPresenter(Context context) {
@@ -79,7 +78,7 @@
     }
 
     /**
-     * A presenter for {@link com.android.tv.dvr.ui.list.SchedulesHeaderRow.DateHeaderRow}.
+     * A presenter for {@link SchedulesHeaderRow.DateHeaderRow}.
      */
     public static class DateHeaderRowPresenter extends SchedulesHeaderRowPresenter {
         public DateHeaderRowPresenter(Context context) {
@@ -93,7 +92,7 @@
 
         /**
          * A ViewHolder for
-         * {@link com.android.tv.dvr.ui.list.SchedulesHeaderRow.DateHeaderRow}.
+         * {@link SchedulesHeaderRow.DateHeaderRow}.
          */
         public static class DateHeaderRowViewHolder extends SchedulesHeaderRowViewHolder {
             public DateHeaderRowViewHolder(Context context, ViewGroup parent) {
@@ -152,9 +151,9 @@
             headerViewHolder.mSeriesSettingsButton.setOnClickListener(new OnClickListener() {
                 @Override
                 public void onClick(View view) {
-                    // TODO: pass channel list for settings.
                     DvrUiHelper.startSeriesSettingsActivity(getContext(),
-                            header.getSeriesRecording().getId(), null, false, false, false);
+                            header.getSeriesRecording().getId(),
+                            header.getPrograms(), false, false, false, null);
                 }
             });
             headerViewHolder.mToggleStartStopButton.setOnClickListener(new OnClickListener() {
@@ -169,9 +168,9 @@
                                 .build();
                         TvApplication.getSingletons(getContext()).getDvrManager()
                                 .updateSeriesRecording(seriesRecording);
-                        // TODO: pass channel list for settings.
                         DvrUiHelper.startSeriesSettingsActivity(getContext(),
-                                header.getSeriesRecording().getId(), null, false, false, false);
+                                header.getSeriesRecording().getId(),
+                                header.getPrograms(), false, false, false, null);
                     } else {
                         DvrUiHelper.showCancelAllSeriesRecordingDialog(
                                 (DvrSchedulesActivity) view.getContext(),
@@ -182,11 +181,8 @@
         }
 
         private void setTextDrawable(TextView textView, Drawable drawableStart) {
-            if (mLtr) {
-                textView.setCompoundDrawablesWithIntrinsicBounds(drawableStart, null, null, null);
-            } else {
-                textView.setCompoundDrawablesWithIntrinsicBounds(null, null, drawableStart, null);
-            }
+            textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, null, null,
+                    null);
         }
 
         /**
diff --git a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
index 3b49377..6b6de8b 100644
--- a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
+++ b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowAdapter.java
@@ -31,8 +31,8 @@
 import com.android.tv.data.Program;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ScheduledRecording;
-import com.android.tv.dvr.SeriesRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.dvr.ui.list.SchedulesHeaderRow.SeriesRecordingHeaderRow;
 import com.android.tv.util.Utils;
 
@@ -46,7 +46,7 @@
  * An adapter for series schedule row.
  */
 @TargetApi(Build.VERSION_CODES.N)
-public class SeriesScheduleRowAdapter extends ScheduleRowAdapter {
+class SeriesScheduleRowAdapter extends ScheduleRowAdapter {
     private static final String TAG = "SeriesRowAdapter";
     private static final boolean DEBUG = false;
 
@@ -96,7 +96,7 @@
         Collections.sort(sortedPrograms);
         List<EpisodicProgramRow> rows = new ArrayList<>();
         mHeaderRow = new SeriesRecordingHeaderRow(mSeriesRecording.getTitle(),
-                null, sortedPrograms.size(), mSeriesRecording);
+                null, sortedPrograms.size(), mSeriesRecording, programs);
         for (Program program : sortedPrograms) {
             ScheduledRecording schedule =
                     mDataManager.getScheduledRecordingForProgramId(program.getId());
@@ -145,7 +145,7 @@
         if (index != -1) {
             EpisodicProgramRow row = (EpisodicProgramRow) get(index);
             if (!row.isStartRecordingRequested()) {
-                row.setSchedule(schedule);
+                setScheduleToRow(row, schedule);
                 notifyArrayItemRangeChanged(index, 1);
             }
         }
@@ -195,12 +195,10 @@
                     if (!isStartOrStopRequested()) {
                         executePendingUpdate();
                     }
-                    row.setSchedule(schedule);
+                    setScheduleToRow(row, schedule);
                 }
-            } else if (willBeKept(schedule)) {
-                row.setSchedule(schedule);
             } else {
-                row.setSchedule(null);
+                setScheduleToRow(row, schedule);
             }
             notifyArrayItemRangeChanged(index, 1);
         }
@@ -213,6 +211,14 @@
         }
     }
 
+    private void setScheduleToRow(ScheduleRow row, ScheduledRecording schedule) {
+        if (schedule != null && willBeKept(schedule)) {
+            row.setSchedule(schedule);
+        } else {
+            row.setSchedule(null);
+        }
+    }
+
     private int findRowIndexByProgramId(long programId) {
         for (int i = 0; i < size(); i++) {
             Object item = get(i);
diff --git a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java
index 5d88579..c8503e0 100644
--- a/src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java
+++ b/src/com/android/tv/dvr/ui/list/SeriesScheduleRowPresenter.java
@@ -22,13 +22,13 @@
 
 import com.android.tv.R;
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.dvr.DvrUiHelper;
+import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.util.Utils;
 
 /**
  * A RowPresenter for series schedule row.
  */
-public class SeriesScheduleRowPresenter extends ScheduleRowPresenter {
+class SeriesScheduleRowPresenter extends ScheduleRowPresenter {
     private static final String TAG = "SeriesRowPresenter";
 
     private boolean mLtr;
@@ -74,13 +74,8 @@
             viewHolder.getProgramTitleView().setCompoundDrawablePadding(getContext()
                     .getResources().getDimensionPixelOffset(
                             R.dimen.dvr_schedules_warning_icon_padding));
-            if (mLtr) {
-                viewHolder.getProgramTitleView().setCompoundDrawablesWithIntrinsicBounds(
-                        R.drawable.ic_warning_gray600_36dp, 0, 0, 0);
-            } else {
-                viewHolder.getProgramTitleView().setCompoundDrawablesWithIntrinsicBounds(
-                        0, 0, R.drawable.ic_warning_gray600_36dp, 0);
-            }
+            viewHolder.getProgramTitleView().setCompoundDrawablesRelativeWithIntrinsicBounds(
+                    R.drawable.ic_warning_gray600_36dp, 0, 0, 0);
         } else {
             viewHolder.getProgramTitleView().setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
         }
@@ -88,9 +83,7 @@
 
     @Override
     protected void onInfoClicked(ScheduleRow row) {
-        if (row.getSchedule() != null) {
-            DvrUiHelper.startSchedulesActivity(getContext(), row.getSchedule());
-        }
+        DvrUiHelper.startSchedulesActivity(getContext(), row.getSchedule());
     }
 
     @Override
diff --git a/src/com/android/tv/dvr/DvrPlaybackActivity.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
similarity index 62%
rename from src/com/android/tv/dvr/DvrPlaybackActivity.java
rename to src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
index 5deda44..6824cfe 100644
--- a/src/com/android/tv/dvr/DvrPlaybackActivity.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackActivity.java
@@ -14,32 +14,38 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.ui.playback;
 
 import android.app.Activity;
+import android.content.ContentUris;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.dvr.ui.DvrPlaybackOverlayFragment;
+import com.android.tv.dialog.PinDialogFragment.OnPinCheckedListener;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.util.Utils;
 
 /**
  * Activity to play a {@link RecordedProgram}.
  */
-public class DvrPlaybackActivity extends Activity {
+public class DvrPlaybackActivity extends Activity implements OnPinCheckedListener {
     private static final String TAG = "DvrPlaybackActivity";
     private static final boolean DEBUG = false;
 
     private DvrPlaybackOverlayFragment mOverlayFragment;
+    private OnPinCheckedListener mOnPinCheckedListener;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         TvApplication.setCurrentRunningProcess(this, true);
         if (DEBUG) Log.d(TAG, "onCreate");
         super.onCreate(savedInstanceState);
+        setIntent(createProgramIntent(getIntent()));
         setContentView(R.layout.activity_dvr_playback);
         mOverlayFragment = (DvrPlaybackOverlayFragment) getFragmentManager()
                 .findFragmentById(R.id.dvr_playback_controls_fragment);
@@ -54,7 +60,8 @@
 
     @Override
     protected void onNewIntent(Intent intent) {
-        mOverlayFragment.onNewIntent(intent);
+        setIntent(createProgramIntent(intent));
+        mOverlayFragment.onNewIntent(createProgramIntent(intent));
     }
 
     @Override
@@ -64,4 +71,24 @@
         mOverlayFragment.onWindowSizeChanged((int) (newConfig.screenWidthDp * density),
                 (int) (newConfig.screenHeightDp * density));
     }
+
+    private Intent createProgramIntent(Intent intent) {
+        if (Intent.ACTION_VIEW.equals(intent.getAction())) {
+            Uri uri = intent.getData();
+            long recordedProgramId = ContentUris.parseId(uri);
+            intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, recordedProgramId);
+        }
+        return intent;
+    }
+
+    @Override
+    public void onPinChecked(boolean checked, int type, String rating) {
+        if (mOnPinCheckedListener != null) {
+            mOnPinCheckedListener.onPinChecked(checked, type, rating);
+        }
+    }
+
+    void setOnPinCheckListener(OnPinCheckedListener listener) {
+        mOnPinCheckedListener = listener;
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackCardPresenter.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackCardPresenter.java
new file mode 100644
index 0000000..8ef0041
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackCardPresenter.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 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.dvr.ui.playback;
+
+import android.content.Context;
+
+import com.android.tv.R;
+import com.android.tv.dvr.ui.browse.RecordedProgramPresenter;
+import com.android.tv.dvr.ui.browse.RecordingCardView;
+
+/**
+ * This class is used to generate Views and bind Objects for related recordings in DVR playback.
+ */
+class DvrPlaybackCardPresenter extends RecordedProgramPresenter {
+    private final int mRelatedRecordingCardWidth;
+    private final int mRelatedRecordingCardHeight;
+
+    DvrPlaybackCardPresenter(Context context) {
+        super(context);
+        mRelatedRecordingCardWidth =
+                context.getResources().getDimensionPixelSize(R.dimen.dvr_related_recordings_width);
+        mRelatedRecordingCardHeight =
+                context.getResources().getDimensionPixelSize(R.dimen.dvr_related_recordings_height);
+    }
+
+    @Override
+    public DvrItemViewHolder onCreateDvrItemViewHolder() {
+        return new RecordedProgramViewHolder(new RecordingCardView(
+                getContext(), mRelatedRecordingCardWidth, mRelatedRecordingCardHeight, true), null);
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/DvrPlaybackControlHelper.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
similarity index 67%
rename from src/com/android/tv/dvr/ui/DvrPlaybackControlHelper.java
rename to src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
index 0bc4ecb..1a6ae18 100644
--- a/src/com/android/tv/dvr/ui/DvrPlaybackControlHelper.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackControlHelper.java
@@ -14,66 +14,80 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.dvr.ui.playback;
 
 import android.app.Activity;
+import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.media.MediaMetadata;
 import android.media.session.MediaController;
 import android.media.session.MediaController.TransportControls;
 import android.media.session.PlaybackState;
-import android.support.v17.leanback.app.PlaybackControlGlue;
+import android.media.tv.TvTrackInfo;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v17.leanback.media.PlaybackControlGlue;
 import android.support.v17.leanback.widget.AbstractDetailsDescriptionPresenter;
 import android.support.v17.leanback.widget.Action;
-import android.support.v17.leanback.widget.OnActionClickedListener;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
 import android.support.v17.leanback.widget.PlaybackControlsRow;
+import android.support.v17.leanback.widget.PlaybackControlsRow.ClosedCaptioningAction;
+import android.support.v17.leanback.widget.PlaybackControlsRow.MultiAction;
 import android.support.v17.leanback.widget.PlaybackControlsRowPresenter;
 import android.support.v17.leanback.widget.RowPresenter;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.View;
-
 import com.android.tv.R;
 import com.android.tv.util.TimeShiftUtils;
+import java.util.ArrayList;
 
 /**
  * A helper class to assist {@link DvrPlaybackOverlayFragment} to manage its controls row and
  * send command to the media controller. It also helps to update playback states displayed in the
  * fragment according to information the media session provides.
  */
-public class DvrPlaybackControlHelper extends PlaybackControlGlue {
-    private static final String TAG = "DvrPlaybackControlHelper";
+class DvrPlaybackControlHelper extends PlaybackControlGlue {
+    private static final String TAG = "DvrPlaybackControlHelpr";
     private static final boolean DEBUG = false;
 
-    /**
-     * Indicates the ID of the media under playback is unknown.
-     */
-    public static int UNKNOWN_MEDIA_ID = -1;
+    private static final int AUDIO_ACTION_ID = 1001;
 
     private int mPlaybackState = PlaybackState.STATE_NONE;
     private int mPlaybackSpeedLevel;
     private int mPlaybackSpeedId;
     private boolean mReadyToControl;
 
+    private final DvrPlaybackOverlayFragment mFragment;
     private final MediaController mMediaController;
     private final MediaController.Callback mMediaControllerCallback = new MediaControllerCallback();
     private final TransportControls mTransportControls;
     private final int mExtraPaddingTopForNoDescription;
+    private final MultiAction mClosedCaptioningAction;
+    private final MultiAction mMultiAudioAction;
+    private ArrayObjectAdapter mSecondaryActionsAdapter;
 
-    public DvrPlaybackControlHelper(Activity activity, DvrPlaybackOverlayFragment overlayFragment) {
-        super(activity, overlayFragment, new int[TimeShiftUtils.MAX_SPEED_LEVEL + 1]);
+    DvrPlaybackControlHelper(Activity activity, DvrPlaybackOverlayFragment overlayFragment) {
+        super(activity, new int[TimeShiftUtils.MAX_SPEED_LEVEL + 1]);
+        mFragment = overlayFragment;
         mMediaController = activity.getMediaController();
         mMediaController.registerCallback(mMediaControllerCallback);
         mTransportControls = mMediaController.getTransportControls();
         mExtraPaddingTopForNoDescription = activity.getResources()
                 .getDimensionPixelOffset(R.dimen.dvr_playback_controls_extra_padding_top);
+        mClosedCaptioningAction = new ClosedCaptioningAction(activity);
+        mMultiAudioAction = new MultiAudioAction(activity);
+        createControlsRowPresenter();
     }
 
-    @Override
-    public PlaybackControlsRowPresenter createControlsRowAndPresenter() {
+    void createControlsRow() {
         PlaybackControlsRow controlsRow = new PlaybackControlsRow(this);
         setControlsRow(controlsRow);
+        mSecondaryActionsAdapter = (ArrayObjectAdapter) controlsRow.getSecondaryActionsAdapter();
+    }
+
+    private void createControlsRowPresenter() {
         AbstractDetailsDescriptionPresenter detailsPresenter =
                 new AbstractDetailsDescriptionPresenter() {
             @Override
@@ -112,30 +126,31 @@
                 .getColor(R.color.play_controls_progress_bar_watched));
         presenter.setBackgroundColor(getContext().getResources()
                 .getColor(R.color.play_controls_body_background_enabled));
-        presenter.setOnActionClickedListener(new OnActionClickedListener() {
-            @Override
-            public void onActionClicked(Action action) {
-                if (mReadyToControl) {
-                    DvrPlaybackControlHelper.super.onActionClicked(action);
-                }
+        setControlsRowPresenter(presenter);
+    }
+
+    @Override
+    public void onActionClicked(Action action) {
+        if (mReadyToControl) {
+            int trackType;
+            if (action.getId() == mClosedCaptioningAction.getId()) {
+                trackType = TvTrackInfo.TYPE_SUBTITLE;
+            } else if (action.getId() == AUDIO_ACTION_ID) {
+                trackType = TvTrackInfo.TYPE_AUDIO;
+            } else {
+                super.onActionClicked(action);
+                return;
             }
-        });
-        return presenter;
+            ArrayList<TvTrackInfo> trackInfos = mFragment.getTracks(trackType);
+            if (!trackInfos.isEmpty()) {
+                showSideFragment(trackInfos, mFragment.getSelectedTrackId(trackType));
+            }
+        }
     }
 
     @Override
     public boolean onKey(View v, int keyCode, KeyEvent event) {
-        if (mReadyToControl) {
-            if (keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE && event.getAction() == KeyEvent.ACTION_DOWN
-                    && (mPlaybackState == PlaybackState.STATE_FAST_FORWARDING
-                    || mPlaybackState == PlaybackState.STATE_REWINDING)) {
-                // Workaround of b/31489271. Clicks play/pause button first to reset play controls
-                // to "play" state. Then we can pass MEDIA_PAUSE to let playback be paused.
-                onActionClicked(getControlsRow().getActionForKeyCode(keyCode));
-            }
-            return super.onKey(v, keyCode, event);
-        }
-        return false;
+        return mReadyToControl && super.onKey(v, keyCode, event);
     }
 
     @Override
@@ -158,10 +173,10 @@
     /**
      * Returns the ID of the media under playback.
      */
-    public long getMediaId() {
+    public String getMediaId() {
         MediaMetadata mediaMetadata = mMediaController.getMetadata();
-        return mediaMetadata == null ? UNKNOWN_MEDIA_ID
-                : mediaMetadata.getLong(MediaMetadata.METADATA_KEY_MEDIA_ID);
+        return mediaMetadata == null ? null
+                : mediaMetadata.getString(MediaMetadata.METADATA_KEY_MEDIA_ID);
     }
 
     @Override
@@ -213,12 +228,45 @@
     /**
      * Unregister media controller's callback.
      */
-    public void unregisterCallback() {
+    void unregisterCallback() {
         mMediaController.unregisterCallback(mMediaControllerCallback);
     }
 
+    /**
+     * Update the secondary controls row.
+     * @param hasClosedCaption {@code true} to show the closed caption selection button,
+     *                         {@code false} to hide it.
+     * @param hasMultiAudio {@code true} to show the audio track selection button,
+     *                      {@code false} to hide it.
+     */
+    void updateSecondaryRow(boolean hasClosedCaption, boolean hasMultiAudio) {
+        if (hasClosedCaption) {
+            if (mSecondaryActionsAdapter.indexOf(mClosedCaptioningAction) < 0) {
+                mSecondaryActionsAdapter.add(0, mClosedCaptioningAction);
+            }
+        } else {
+            mSecondaryActionsAdapter.remove(mClosedCaptioningAction);
+        }
+        if (hasMultiAudio) {
+            if (mSecondaryActionsAdapter.indexOf(mMultiAudioAction) < 0) {
+                mSecondaryActionsAdapter.add(mMultiAudioAction);
+            }
+        } else {
+            mSecondaryActionsAdapter.remove(mMultiAudioAction);
+        }
+        getHost().notifyPlaybackRowChanged();
+    }
+
+    @Nullable
+    Boolean hasSecondaryRow() {
+        if (mSecondaryActionsAdapter == null) {
+            return null;
+        }
+        return mSecondaryActionsAdapter.size() != 0;
+    }
+
     @Override
-    protected void startPlayback(int speedId) {
+    public void play(int speedId) {
         if (getCurrentSpeedId() == speedId) {
             return;
         }
@@ -232,23 +280,16 @@
     }
 
     @Override
-    protected void pausePlayback() {
+    public void pause() {
         mTransportControls.pause();
     }
 
-    @Override
-    protected void skipToNext() {
-        // Do nothing.
-    }
-
-    @Override
-    protected void skipToPrevious() {
-        // Do nothing.
-    }
-
-    @Override
-    protected void onRowChanged(PlaybackControlsRow row) {
-        // Do nothing.
+    /**
+     * Notifies closed caption being enabled/disabled to update related UI.
+     */
+    void onSubtitleTrackStateChanged(boolean enabled) {
+        mClosedCaptioningAction.setIndex(enabled ?
+                ClosedCaptioningAction.ON : ClosedCaptioningAction.OFF);
     }
 
     private void onStateChanged(int state, long positionMs, int speedLevel) {
@@ -297,6 +338,19 @@
         onStateChanged();
     }
 
+    private void showSideFragment(ArrayList<TvTrackInfo> trackInfos, String selectedTrackId) {
+        Bundle args = new Bundle();
+        args.putParcelableArrayList(DvrPlaybackSideFragment.TRACK_INFOS, trackInfos);
+        args.putString(DvrPlaybackSideFragment.SELECTED_TRACK_ID, selectedTrackId);
+        DvrPlaybackSideFragment sideFragment = new DvrPlaybackSideFragment();
+        sideFragment.setArguments(args);
+        mFragment.getFragmentManager().beginTransaction()
+                .hide(mFragment)
+                .replace(R.id.dvr_playback_side_fragment, sideFragment)
+                .addToBackStack(null)
+                .commit();
+    }
+
     private class MediaControllerCallback extends MediaController.Callback {
         @Override
         public void onPlaybackStateChanged(PlaybackState state) {
@@ -307,7 +361,13 @@
         @Override
         public void onMetadataChanged(MediaMetadata metadata) {
             DvrPlaybackControlHelper.this.onMetadataChanged();
-            ((DvrPlaybackOverlayFragment) getFragment()).onMediaControllerUpdated();
+        }
+    }
+
+    private static class MultiAudioAction extends MultiAction {
+        MultiAudioAction(Context context) {
+            super(AUDIO_ACTION_ID);
+            setDrawables(new Drawable[]{context.getDrawable(R.drawable.ic_tvoption_multi_track)});
         }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/DvrPlaybackMediaSessionHelper.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackMediaSessionHelper.java
similarity index 75%
rename from src/com/android/tv/dvr/DvrPlaybackMediaSessionHelper.java
rename to src/com/android/tv/dvr/ui/playback/DvrPlaybackMediaSessionHelper.java
index 9759a85..843d2db 100644
--- a/src/com/android/tv/dvr/DvrPlaybackMediaSessionHelper.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackMediaSessionHelper.java
@@ -14,7 +14,7 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.ui.playback;
 
 import android.app.Activity;
 import android.content.Intent;
@@ -31,14 +31,16 @@
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
+import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.data.ChannelDataManager;
-import com.android.tv.dvr.ui.DvrPlaybackOverlayFragment;
+import com.android.tv.dvr.DvrWatchedPositionManager;
+import com.android.tv.dvr.data.RecordedProgram;
 import com.android.tv.util.ImageLoader;
 import com.android.tv.util.TimeShiftUtils;
 import com.android.tv.util.Utils;
 
-public class DvrPlaybackMediaSessionHelper {
+class DvrPlaybackMediaSessionHelper {
     private static final String TAG = "DvrPlaybackMediaSessionHelper";
     private static final boolean DEBUG = false;
 
@@ -102,6 +104,7 @@
         }
         if (mMediaSession != null) {
             mMediaSession.release();
+            mMediaSession = null;
         }
     }
 
@@ -179,83 +182,88 @@
             cardTitleText = (channel != null) ? channel.getDisplayName()
                     : mActivity.getString(R.string.no_program_information);
         }
-        updateMediaMetadata(program.getId(), cardTitleText, program.getDescription(),
-                mProgramDurationMs, null, 0);
+        final MediaMetadata currentMetadata = updateMetadataTextInfo(program.getId(), cardTitleText,
+                program.getDescription(), mProgramDurationMs);
         String posterArtUri = program.getPosterArtUri();
         if (posterArtUri == null) {
             posterArtUri = TvContract.buildChannelLogoUri(program.getChannelId()).toString();
         }
-        updatePosterArt(program, cardTitleText, program.getDescription(),
-                mProgramDurationMs, null, posterArtUri);
+        updatePosterArt(program, currentMetadata, null, posterArtUri);
         mMediaSession.setActive(true);
     }
 
-    private void updatePosterArt(RecordedProgram program, String cardTitleText,
-            String cardSubtitleText, long duration,
+    private void updatePosterArt(RecordedProgram program, MediaMetadata currentMetadata,
             @Nullable Bitmap posterArt, @Nullable String posterArtUri) {
         if (posterArt != null) {
-            updateMediaMetadata(program.getId(), cardTitleText,
-                    cardSubtitleText, duration, posterArt, 0);
+            updateMetadataImageInfo(program, currentMetadata, posterArt, 0);
         } else if (posterArtUri != null) {
             ImageLoader.loadBitmap(mActivity, posterArtUri, mNowPlayingCardWidth,
-                    mNowPlayingCardHeight, new ProgramPosterArtCallback(
-                            mActivity, program, cardTitleText, cardSubtitleText, duration));
+                    mNowPlayingCardHeight,
+                    new ProgramPosterArtCallback(mActivity, program, currentMetadata));
         } else {
-            updateMediaMetadata(program.getId(), cardTitleText,
-                    cardSubtitleText, duration, null, R.drawable.default_now_card);
+            updateMetadataImageInfo(program, currentMetadata, null, R.drawable.default_now_card);
         }
     }
 
     private class ProgramPosterArtCallback extends
             ImageLoader.ImageLoaderCallback<Activity> {
-        private RecordedProgram mRecordedProgram;
-        private String mCardTitleText;
-        private String mCardSubtitleText;
-        private long mDuration;
+        private final RecordedProgram mRecordedProgram;
+        private final MediaMetadata mCurrentMetadata;
 
         public ProgramPosterArtCallback(Activity activity, RecordedProgram program,
-                String cardTitleText, String cardSubtitleText, long duration) {
+                MediaMetadata metadata) {
             super(activity);
             mRecordedProgram = program;
-            mCardTitleText = cardTitleText;
-            mCardSubtitleText = cardSubtitleText;
-            mDuration = duration;
+            mCurrentMetadata = metadata;
         }
 
         @Override
         public void onBitmapLoaded(Activity activity, @Nullable Bitmap posterArt) {
             if (isCurrentProgram(mRecordedProgram)) {
-                updatePosterArt(mRecordedProgram, mCardTitleText,
-                        mCardSubtitleText, mDuration, posterArt, null);
+                updatePosterArt(mRecordedProgram, mCurrentMetadata, posterArt, null);
             }
         }
     }
 
-    private void updateMediaMetadata(final long programId, final String title,
-            final String subtitle, final long duration,
-            final Bitmap posterArt, final int imageResId) {
-        new AsyncTask<Void, Void, Void>() {
-            @Override
-            protected Void doInBackground(Void... arg0) {
-                MediaMetadata.Builder builder = new MediaMetadata.Builder();
-                builder.putLong(MediaMetadata.METADATA_KEY_MEDIA_ID, programId)
-                        .putString(MediaMetadata.METADATA_KEY_TITLE, title)
-                        .putLong(MediaMetadata.METADATA_KEY_DURATION, duration);
-                if (subtitle != null) {
-                    builder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE, subtitle);
-                }
-                Bitmap programPosterArt = posterArt;
-                if (programPosterArt == null && imageResId != 0) {
-                    programPosterArt =
-                            BitmapFactory.decodeResource(mActivity.getResources(), imageResId);
-                }
-                if (programPosterArt != null) {
-                    builder.putBitmap(MediaMetadata.METADATA_KEY_ART, programPosterArt);
-                }
+    private MediaMetadata updateMetadataTextInfo(final long programId, final String title,
+            final String subtitle, final long duration) {
+        MediaMetadata.Builder builder = new MediaMetadata.Builder();
+        builder.putString(MediaMetadata.METADATA_KEY_MEDIA_ID, Long.toString(programId))
+                .putString(MediaMetadata.METADATA_KEY_TITLE, title)
+                .putLong(MediaMetadata.METADATA_KEY_DURATION, duration);
+        if (subtitle != null) {
+            builder.putString(MediaMetadata.METADATA_KEY_DISPLAY_SUBTITLE, subtitle);
+        }
+        MediaMetadata metadata = builder.build();
+        mMediaSession.setMetadata(metadata);
+        return metadata;
+    }
+
+    private void updateMetadataImageInfo(final RecordedProgram program,
+            final MediaMetadata currentMetadata, final Bitmap posterArt, final int imageResId) {
+        if (mMediaSession != null && (posterArt != null || imageResId != 0)) {
+            MediaMetadata.Builder builder = new MediaMetadata.Builder(currentMetadata);
+            if (posterArt != null) {
+                builder.putBitmap(MediaMetadata.METADATA_KEY_ART, posterArt);
                 mMediaSession.setMetadata(builder.build());
-                return null;
+            } else {
+                new AsyncTask<Void, Void, Bitmap>() {
+                    @Override
+                    protected Bitmap doInBackground(Void... arg0) {
+                        return BitmapFactory.decodeResource(mActivity.getResources(), imageResId);
+                    }
+
+                    @Override
+                    protected void onPostExecute(Bitmap programPosterArt) {
+                        if (mMediaSession != null && programPosterArt != null
+                                && isCurrentProgram(program)) {
+                            builder.putBitmap(MediaMetadata.METADATA_KEY_ART, programPosterArt);
+                            mMediaSession.setMetadata(builder.build());
+                        }
+                    }
+                }.execute();
             }
-        }.execute();
+        }
     }
 
     // An event was triggered by MediaController.TransportControls and must be handled here.
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java
new file mode 100644
index 0000000..783ae68
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackOverlayFragment.java
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.playback;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Point;
+import android.hardware.display.DisplayManager;
+import android.media.tv.TvContentRating;
+import android.media.tv.TvTrackInfo;
+import android.os.Bundle;
+import android.media.session.PlaybackState;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvView;
+import android.support.v17.leanback.app.PlaybackFragment;
+import android.support.v17.leanback.app.PlaybackFragmentGlueHost;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.BaseOnItemViewClickedListener;
+import android.support.v17.leanback.widget.ClassPresenterSelector;
+import android.support.v17.leanback.widget.HeaderItem;
+import android.support.v17.leanback.widget.ListRow;
+import android.support.v17.leanback.widget.Presenter;
+import android.support.v17.leanback.widget.RowPresenter;
+import android.support.v17.leanback.widget.SinglePresenterSelector;
+import android.view.Display;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+import android.util.Log;
+
+import com.android.tv.R;
+import com.android.tv.TvApplication;
+import com.android.tv.data.BaseProgram;
+import com.android.tv.dialog.PinDialogFragment;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.ui.SortedArrayAdapter;
+import com.android.tv.dvr.ui.browse.DvrListRowPresenter;
+import com.android.tv.dvr.ui.browse.RecordingCardView;
+import com.android.tv.parental.ContentRatingsManager;
+import com.android.tv.util.TvSettings;
+import com.android.tv.util.TvTrackInfoUtils;
+import com.android.tv.util.Utils;
+
+import java.util.List;
+import java.util.ArrayList;
+
+public class DvrPlaybackOverlayFragment extends PlaybackFragment {
+    // TODO: Handles audio focus. Deals with block and ratings.
+    private static final String TAG = "DvrPlaybackOverlayFrag";
+    private static final boolean DEBUG = false;
+
+    private static final String MEDIA_SESSION_TAG = "com.android.tv.dvr.mediasession";
+    private static final float DISPLAY_ASPECT_RATIO_EPSILON = 0.01f;
+
+    // mProgram is only used to store program from intent. Don't use it elsewhere.
+    private RecordedProgram mProgram;
+    private DvrPlayer mDvrPlayer;
+    private DvrPlaybackMediaSessionHelper mMediaSessionHelper;
+    private DvrPlaybackControlHelper mPlaybackControlHelper;
+    private ArrayObjectAdapter mRowsAdapter;
+    private SortedArrayAdapter<BaseProgram> mRelatedRecordingsRowAdapter;
+    private DvrPlaybackCardPresenter mRelatedRecordingCardPresenter;
+    private DvrDataManager mDvrDataManager;
+    private ContentRatingsManager mContentRatingsManager;
+    private TvView mTvView;
+    private View mBlockScreenView;
+    private ListRow mRelatedRecordingsRow;
+    private int mVerticalPaddingBase;
+    private int mPaddingWithoutRelatedRow;
+    private int mPaddingWithoutSecondaryRow;
+    private int mWindowWidth;
+    private int mWindowHeight;
+    private float mAppliedAspectRatio;
+    private float mWindowAspectRatio;
+    private boolean mPinChecked;
+    private boolean mStarted;
+    private DvrPlayer.OnTrackSelectedListener mOnSubtitleTrackSelectedListener =
+            new DvrPlayer.OnTrackSelectedListener() {
+                @Override
+                public void onTrackSelected(String selectedTrackId) {
+                    mPlaybackControlHelper.onSubtitleTrackStateChanged(selectedTrackId != null);
+                    mRowsAdapter.notifyArrayItemRangeChanged(0, 1);
+                }
+            };
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        if (DEBUG) Log.d(TAG, "onCreate");
+        super.onCreate(savedInstanceState);
+        mVerticalPaddingBase = getActivity().getResources()
+                .getDimensionPixelOffset(R.dimen.dvr_playback_overlay_padding_top_base);
+        mPaddingWithoutRelatedRow = getActivity().getResources()
+                .getDimensionPixelOffset(R.dimen.dvr_playback_overlay_padding_top_no_related_row);
+        mPaddingWithoutSecondaryRow = getActivity().getResources()
+                .getDimensionPixelOffset(R.dimen.dvr_playback_overlay_padding_top_no_secondary_row);
+        mDvrDataManager = TvApplication.getSingletons(getActivity()).getDvrDataManager();
+        mContentRatingsManager = TvApplication.getSingletons(getContext())
+                .getTvInputManagerHelper().getContentRatingsManager();
+        if (!mDvrDataManager.isRecordedProgramLoadFinished()) {
+            mDvrDataManager.addRecordedProgramLoadFinishedListener(
+                    new DvrDataManager.OnRecordedProgramLoadFinishedListener() {
+                        @Override
+                        public void onRecordedProgramLoadFinished() {
+                            mDvrDataManager.removeRecordedProgramLoadFinishedListener(this);
+                            if (handleIntent(getActivity().getIntent(), true)) {
+                                setUpRows();
+                                preparePlayback(getActivity().getIntent());
+                            }
+                        }
+                    }
+            );
+        } else if (!handleIntent(getActivity().getIntent(), true)) {
+            return;
+        }
+        Point size = new Point();
+        ((DisplayManager) getContext().getSystemService(Context.DISPLAY_SERVICE))
+                .getDisplay(Display.DEFAULT_DISPLAY).getSize(size);
+        mWindowWidth = size.x;
+        mWindowHeight = size.y;
+        mWindowAspectRatio = mAppliedAspectRatio = (float) mWindowWidth / mWindowHeight;
+        setBackgroundType(PlaybackFragment.BG_LIGHT);
+        setFadingEnabled(true);
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        mStarted = true;
+        updateVerticalPosition();
+    }
+
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        mTvView = (TvView) getActivity().findViewById(R.id.dvr_tv_view);
+        mBlockScreenView = getActivity().findViewById(R.id.block_screen);
+        mDvrPlayer = new DvrPlayer(mTvView);
+        mMediaSessionHelper = new DvrPlaybackMediaSessionHelper(
+                getActivity(), MEDIA_SESSION_TAG, mDvrPlayer, this);
+        mPlaybackControlHelper = new DvrPlaybackControlHelper(getActivity(), this);
+        mRelatedRecordingsRow = getRelatedRecordingsRow();
+        mDvrPlayer.setOnTracksAvailabilityChangedListener(
+                new DvrPlayer.OnTracksAvailabilityChangedListener() {
+                    @Override
+                    public void onTracksAvailabilityChanged(boolean hasClosedCaption,
+                            boolean hasMultiAudio) {
+                        mPlaybackControlHelper.updateSecondaryRow(hasClosedCaption, hasMultiAudio);
+                        if (hasClosedCaption) {
+                            mDvrPlayer.setOnTrackSelectedListener(TvTrackInfo.TYPE_SUBTITLE,
+                                    mOnSubtitleTrackSelectedListener);
+                            selectBestMatchedTrack(TvTrackInfo.TYPE_SUBTITLE);
+                        } else {
+                            mDvrPlayer.setOnTrackSelectedListener(TvTrackInfo.TYPE_SUBTITLE, null);
+                        }
+                        if (hasMultiAudio) {
+                            selectBestMatchedTrack(TvTrackInfo.TYPE_AUDIO);
+                        }
+                        updateVerticalPosition();
+                        mPlaybackControlHelper.getHost().notifyPlaybackRowChanged();
+                    }
+        });
+        mDvrPlayer.setOnAspectRatioChangedListener(new DvrPlayer.OnAspectRatioChangedListener() {
+            @Override
+            public void onAspectRatioChanged(float videoAspectRatio) {
+                updateAspectRatio(videoAspectRatio);
+            }
+        });
+        mPinChecked = getActivity().getIntent()
+                .getBooleanExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_PIN_CHECKED, false);
+        mDvrPlayer.setOnContentBlockedListener(
+                new DvrPlayer.OnContentBlockedListener() {
+                    @Override
+                    public void onContentBlocked(TvContentRating contentRating) {
+                        if (mPinChecked) {
+                            mTvView.unblockContent(contentRating);
+                            return;
+                        }
+                        mBlockScreenView.setVisibility(View.VISIBLE);
+                        getActivity().getMediaController().getTransportControls().pause();
+                        ((DvrPlaybackActivity) getActivity())
+                                .setOnPinCheckListener(
+                                        new PinDialogFragment.OnPinCheckedListener() {
+                                            @Override
+                                            public void onPinChecked(
+                                                    boolean checked, int type, String rating) {
+                                                ((DvrPlaybackActivity) getActivity())
+                                                        .setOnPinCheckListener(null);
+                                                if (checked) {
+                                                    mPinChecked = true;
+                                                    mTvView.unblockContent(contentRating);
+                                                    mBlockScreenView.setVisibility(View.GONE);
+                                                    getActivity()
+                                                            .getMediaController()
+                                                            .getTransportControls()
+                                                            .play();
+                                                }
+                                            }
+                                        });
+                        PinDialogFragment.create(
+                                        PinDialogFragment.PIN_DIALOG_TYPE_UNLOCK_DVR,
+                                        contentRating.flattenToString())
+                                .show(
+                                        getActivity().getFragmentManager(),
+                                        PinDialogFragment.DIALOG_TAG);
+                    }
+                });
+        setOnItemViewClickedListener(new BaseOnItemViewClickedListener() {
+            @Override
+            public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+                    RowPresenter.ViewHolder rowViewHolder, Object row) {
+                if (itemViewHolder.view instanceof RecordingCardView) {
+                    setFadingEnabled(false);
+                    long programId = ((RecordedProgram) itemViewHolder.view.getTag()).getId();
+                    if (DEBUG) Log.d(TAG, "Play Related Recording:" + programId);
+                    Intent intent = new Intent(getContext(), DvrPlaybackActivity.class);
+                    intent.putExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, programId);
+                    getContext().startActivity(intent);
+                }
+            }
+        });
+        if (mProgram != null) {
+            setUpRows();
+            preparePlayback(getActivity().getIntent());
+        }
+    }
+
+    @Override
+    public void onPause() {
+        if (DEBUG) Log.d(TAG, "onPause");
+        super.onPause();
+        if (mMediaSessionHelper.getPlaybackState() == PlaybackState.STATE_FAST_FORWARDING
+                || mMediaSessionHelper.getPlaybackState() == PlaybackState.STATE_REWINDING) {
+            getActivity().getMediaController().getTransportControls().pause();
+        }
+        if (mMediaSessionHelper.getPlaybackState() == PlaybackState.STATE_NONE) {
+            getActivity().requestVisibleBehind(false);
+        } else {
+            getActivity().requestVisibleBehind(true);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        if (DEBUG) Log.d(TAG, "onDestroy");
+        mPlaybackControlHelper.unregisterCallback();
+        mMediaSessionHelper.release();
+        mRelatedRecordingCardPresenter.unbindAllViewHolders();
+        super.onDestroy();
+    }
+
+    /**
+     * Passes the intent to the fragment.
+     */
+    public void onNewIntent(Intent intent) {
+        if (mDvrDataManager.isRecordedProgramLoadFinished() && handleIntent(intent, false)) {
+            preparePlayback(intent);
+        }
+    }
+
+    /**
+     * Should be called when windows' size is changed in order to notify DVR player
+     * to update it's view width/height and position.
+     */
+    public void onWindowSizeChanged(final int windowWidth, final int windowHeight) {
+        mWindowWidth = windowWidth;
+        mWindowHeight = windowHeight;
+        mWindowAspectRatio = (float) mWindowWidth / mWindowHeight;
+        updateAspectRatio(mAppliedAspectRatio);
+    }
+
+    /**
+     * Returns next recorded episode in the same series as now playing program.
+     */
+    public RecordedProgram getNextEpisode(RecordedProgram program) {
+        int position = mRelatedRecordingsRowAdapter.findInsertPosition(program);
+        if (position == mRelatedRecordingsRowAdapter.size()) {
+            return null;
+        } else {
+            return (RecordedProgram) mRelatedRecordingsRowAdapter.get(position);
+        }
+    }
+
+    /**
+     * Returns the tracks of the give type of the current playback.
+
+     * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE}
+     *                  or {@link TvTrackInfo#TYPE_AUDIO}. Or returns {@code null}.
+     */
+    public ArrayList<TvTrackInfo> getTracks(int trackType) {
+        if (trackType == TvTrackInfo.TYPE_AUDIO) {
+            return mDvrPlayer.getAudioTracks();
+        } else if (trackType == TvTrackInfo.TYPE_SUBTITLE) {
+            return mDvrPlayer.getSubtitleTracks();
+        }
+        return null;
+    }
+
+    /**
+     * Returns the ID of the selected track of the given type.
+     */
+    public String getSelectedTrackId(int trackType) {
+        return mDvrPlayer.getSelectedTrackId(trackType);
+    }
+
+    /**
+     * Returns the language setting of the given track type.
+
+     * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE}
+     *                  or {@link TvTrackInfo#TYPE_AUDIO}.
+     * @return {@code null} if no language has been set for the given track type.
+     */
+    TvTrackInfo getTrackSetting(int trackType) {
+        return TvSettings.getDvrPlaybackTrackSettings(getContext(), trackType);
+    }
+
+    /**
+     * Selects the given audio or subtitle track for DVR playback.
+     * @param trackType Should be {@link TvTrackInfo#TYPE_SUBTITLE}
+     *                  or {@link TvTrackInfo#TYPE_AUDIO}.
+     * @param selectedTrack {@code null} to disable the audio or subtitle track according to
+     *                      trackType.
+     */
+    void selectTrack(int trackType, TvTrackInfo selectedTrack) {
+        if (mDvrPlayer.isPlaybackPrepared()) {
+            mDvrPlayer.selectTrack(trackType, selectedTrack);
+        }
+    }
+
+    private boolean handleIntent(Intent intent, boolean finishActivity) {
+        mProgram = getProgramFromIntent(intent);
+        if (mProgram == null) {
+            Toast.makeText(getActivity(), getString(R.string.dvr_program_not_found),
+                    Toast.LENGTH_SHORT).show();
+            if (finishActivity) {
+                getActivity().finish();
+            }
+            return false;
+        }
+        return true;
+    }
+
+    private void selectBestMatchedTrack(int trackType) {
+        TvTrackInfo selectedTrack = getTrackSetting(trackType);
+        if (selectedTrack != null) {
+            TvTrackInfo bestMatchedTrack = TvTrackInfoUtils.getBestTrackInfo(getTracks(trackType),
+                    selectedTrack.getId(), selectedTrack.getLanguage(),
+                    trackType == TvTrackInfo.TYPE_AUDIO ? selectedTrack.getAudioChannelCount() : 0);
+            if (bestMatchedTrack != null && (trackType == TvTrackInfo.TYPE_AUDIO || Utils
+                    .isEqualLanguage(bestMatchedTrack.getLanguage(),
+                            selectedTrack.getLanguage()))) {
+                selectTrack(trackType, bestMatchedTrack);
+                return;
+            }
+        }
+        if (trackType == TvTrackInfo.TYPE_SUBTITLE) {
+            // Disables closed captioning if there's no matched language.
+            selectTrack(TvTrackInfo.TYPE_SUBTITLE, null);
+        }
+    }
+
+    private void updateAspectRatio(float videoAspectRatio) {
+        if (videoAspectRatio <= 0) {
+            // We don't have video's width or height information, use window's aspect ratio.
+            videoAspectRatio = mWindowAspectRatio;
+        }
+        if (Math.abs(mAppliedAspectRatio - videoAspectRatio) < DISPLAY_ASPECT_RATIO_EPSILON) {
+            // No need to change
+            return;
+        }
+        if (Math.abs(mWindowAspectRatio - videoAspectRatio) < DISPLAY_ASPECT_RATIO_EPSILON) {
+            ((ViewGroup) mTvView.getParent()).setPadding(0, 0, 0, 0);
+        } else if (videoAspectRatio < mWindowAspectRatio) {
+            int newPadding = (mWindowWidth - Math.round(mWindowHeight * videoAspectRatio)) / 2;
+            ((ViewGroup) mTvView.getParent()).setPadding(newPadding, 0, newPadding, 0);
+        } else {
+            int newPadding = (mWindowHeight - Math.round(mWindowWidth / videoAspectRatio)) / 2;
+            ((ViewGroup) mTvView.getParent()).setPadding(0, newPadding, 0, newPadding);
+        }
+        mAppliedAspectRatio = videoAspectRatio;
+    }
+
+    private void preparePlayback(Intent intent) {
+        mMediaSessionHelper.setupPlayback(mProgram, getSeekTimeFromIntent(intent));
+        mPlaybackControlHelper.updateSecondaryRow(false, false);
+        getActivity().getMediaController().getTransportControls().prepare();
+        updateRelatedRecordingsRow();
+    }
+
+    private void updateRelatedRecordingsRow() {
+        boolean wasEmpty = (mRelatedRecordingsRowAdapter.size() == 0);
+        mRelatedRecordingsRowAdapter.clear();
+        long programId = mProgram.getId();
+        String seriesId = mProgram.getSeriesId();
+        SeriesRecording seriesRecording = mDvrDataManager.getSeriesRecording(seriesId);
+        if (seriesRecording != null) {
+            if (DEBUG) Log.d(TAG, "Update related recordings with:" + seriesId);
+            List<RecordedProgram> relatedPrograms =
+                    mDvrDataManager.getRecordedPrograms(seriesRecording.getId());
+            for (RecordedProgram program : relatedPrograms) {
+                if (programId != program.getId()) {
+                    mRelatedRecordingsRowAdapter.add(program);
+                }
+            }
+        }
+        if (mRelatedRecordingsRowAdapter.size() == 0) {
+            mRowsAdapter.remove(mRelatedRecordingsRow);
+        } else if (wasEmpty){
+            mRowsAdapter.add(mRelatedRecordingsRow);
+        }
+        updateVerticalPosition();
+        mRowsAdapter.notifyArrayItemRangeChanged(1, 1);
+    }
+
+    private void setUpRows() {
+        mPlaybackControlHelper.createControlsRow();
+        mPlaybackControlHelper.setHost(new PlaybackFragmentGlueHost(this));
+        mRowsAdapter = (ArrayObjectAdapter) getAdapter();
+        ClassPresenterSelector selector =
+                (ClassPresenterSelector) mRowsAdapter.getPresenterSelector();
+        selector.addClassPresenter(ListRow.class, new DvrListRowPresenter(getContext()));
+        mRowsAdapter.setPresenterSelector(selector);
+        if (mStarted) {
+            // If it's started before setting up rows, vertical position has not been updated and
+            // should be updated here.
+            updateVerticalPosition();
+        }
+    }
+
+    private ListRow getRelatedRecordingsRow() {
+        mRelatedRecordingCardPresenter = new DvrPlaybackCardPresenter(getActivity());
+        mRelatedRecordingsRowAdapter = new RelatedRecordingsAdapter(mRelatedRecordingCardPresenter);
+        HeaderItem header = new HeaderItem(0,
+                getActivity().getString(R.string.dvr_playback_related_recordings));
+        return new ListRow(header, mRelatedRecordingsRowAdapter);
+    }
+
+    private RecordedProgram getProgramFromIntent(Intent intent) {
+        long programId = intent.getLongExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_ID, -1);
+        return mDvrDataManager.getRecordedProgram(programId);
+    }
+
+    private long getSeekTimeFromIntent(Intent intent) {
+        return intent.getLongExtra(Utils.EXTRA_KEY_RECORDED_PROGRAM_SEEK_TIME,
+                TvInputManager.TIME_SHIFT_INVALID_TIME);
+    }
+
+    private void updateVerticalPosition() {
+        Boolean hasSecondaryRow = mPlaybackControlHelper.hasSecondaryRow();
+        if (hasSecondaryRow == null) {
+            return;
+        }
+
+        int verticalPadding = mVerticalPaddingBase;
+        if (mRelatedRecordingsRowAdapter.size() == 0) {
+            verticalPadding += mPaddingWithoutRelatedRow;
+        }
+        if (!hasSecondaryRow) {
+            verticalPadding += mPaddingWithoutSecondaryRow;
+        }
+        Fragment fragment = getChildFragmentManager().findFragmentById(R.id.playback_controls_dock);
+        View view = fragment == null ? null : fragment.getView();
+        if (view != null) {
+            view.setTranslationY(verticalPadding);
+        }
+    }
+
+    private class RelatedRecordingsAdapter extends SortedArrayAdapter<BaseProgram> {
+        RelatedRecordingsAdapter(DvrPlaybackCardPresenter presenter) {
+            super(new SinglePresenterSelector(presenter), BaseProgram.EPISODE_COMPARATOR);
+        }
+
+        @Override
+        public long getId(BaseProgram item) {
+            return item.getId();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java b/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java
new file mode 100644
index 0000000..e49870f
--- /dev/null
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlaybackSideFragment.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2016 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.dvr.ui.playback;
+
+import android.media.tv.TvTrackInfo;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v17.leanback.app.GuidedStepFragment;
+import android.support.v17.leanback.widget.GuidedAction;
+import android.text.TextUtils;
+import android.transition.Transition;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.tv.R;
+import com.android.tv.util.TvSettings;
+
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * Fragment for DVR playback closed-caption/multi-audio settings.
+ */
+public class DvrPlaybackSideFragment extends GuidedStepFragment {
+    /**
+     * The tag for passing track infos to side fragments.
+     */
+    public static final String TRACK_INFOS = "dvr_key_track_infos";
+    /**
+     * The tag for passing selected track's ID to side fragments.
+     */
+    public static final String SELECTED_TRACK_ID = "dvr_key_selected_track_id";
+
+    private static final int ACTION_ID_NO_SUBTITLE = -1;
+    private static final int CHECK_SET_ID = 1;
+
+    private List<TvTrackInfo> mTrackInfos;
+    private String mSelectedTrackId;
+    private TvTrackInfo mSelectedTrack;
+    private int mTrackType;
+    private DvrPlaybackOverlayFragment mOverlayFragment;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        mTrackInfos = getArguments().getParcelableArrayList(TRACK_INFOS);
+        mTrackType = mTrackInfos.get(0).getType();
+        mSelectedTrackId = getArguments().getString(SELECTED_TRACK_ID);
+        mOverlayFragment = ((DvrPlaybackOverlayFragment) getFragmentManager()
+                .findFragmentById(R.id.dvr_playback_controls_fragment));
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public View onCreateBackgroundView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        View backgroundView = super.onCreateBackgroundView(inflater, container, savedInstanceState);
+        backgroundView.setBackgroundColor(getResources()
+                .getColor(R.color.lb_playback_controls_background_light));
+        return backgroundView;
+    }
+
+    @Override
+    public void onCreateActions(@NonNull List<GuidedAction> actions, Bundle savedInstanceState) {
+        if (mTrackType == TvTrackInfo.TYPE_SUBTITLE) {
+            actions.add(new GuidedAction.Builder(getActivity())
+                    .id(ACTION_ID_NO_SUBTITLE)
+                    .title(getString(R.string.closed_caption_option_item_off))
+                    .checkSetId(CHECK_SET_ID)
+                    .checked(mSelectedTrackId == null)
+                    .build());
+        }
+        for (int i = 0; i < mTrackInfos.size(); i++) {
+            TvTrackInfo info = mTrackInfos.get(i);
+            boolean checked = TextUtils.equals(info.getId(), mSelectedTrackId);
+            GuidedAction action = new GuidedAction.Builder(getActivity())
+                    .id(i)
+                    .title(getTrackLabel(info, i))
+                    .checkSetId(CHECK_SET_ID)
+                    .checked(checked)
+                    .build();
+            actions.add(action);
+            if (checked) {
+                mSelectedTrack = info;
+            }
+        }
+    }
+
+    @Override
+    public void onGuidedActionFocused(GuidedAction action) {
+        int actionId = (int) action.getId();
+        mOverlayFragment.selectTrack(mTrackType, actionId < 0 ? null : mTrackInfos.get(actionId));
+    }
+
+    @Override
+    public void onGuidedActionClicked(GuidedAction action) {
+        int actionId = (int) action.getId();
+        mSelectedTrack = actionId < 0 ? null : mTrackInfos.get(actionId);
+        TvSettings.setDvrPlaybackTrackSettings(getContext(), mTrackType, mSelectedTrack);
+        getFragmentManager().popBackStack();
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        // Workaround: when overlay fragment is faded out, any focus will lost due to overlay
+        // fragment's implementation. So we disable overlay fragment's fading here to prevent
+        // losing focus while users are interacting with the side fragment.
+        mOverlayFragment.setFadingEnabled(false);
+    }
+
+    @Override
+    public void onStop() {
+        super.onStop();
+        // We disable fading of overlay fragment to prevent side fragment from losing focus,
+        // therefore we should resume it here.
+        mOverlayFragment.setFadingEnabled(true);
+        mOverlayFragment.selectTrack(mTrackType, mSelectedTrack);
+    }
+
+    private String getTrackLabel(TvTrackInfo track, int trackIndex) {
+        if (track.getLanguage() != null) {
+            return new Locale(track.getLanguage()).getDisplayName();
+        }
+        return track.getType() == TvTrackInfo.TYPE_SUBTITLE ?
+                getString(R.string.closed_caption_unknown_language, trackIndex + 1)
+                : getString(R.string.multi_audio_unknown_language);
+    }
+
+    @Override
+    protected void onProvideFragmentTransitions() {
+        super.onProvideFragmentTransitions();
+        // Excludes the background scrim from transition to prevent the blinking caused by
+        // hiding the overlay fragment and sliding in the side fragment at the same time.
+        Transition t = getEnterTransition();
+        if (t != null) {
+            t.excludeTarget(R.id.guidedstep_background, true);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/dvr/DvrPlayer.java b/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
similarity index 62%
rename from src/com/android/tv/dvr/DvrPlayer.java
rename to src/com/android/tv/dvr/ui/playback/DvrPlayer.java
index 5656655..7226c66 100644
--- a/src/com/android/tv/dvr/DvrPlayer.java
+++ b/src/com/android/tv/dvr/ui/playback/DvrPlayer.java
@@ -14,20 +14,24 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.ui.playback;
 
 import android.media.PlaybackParams;
+import android.media.session.PlaybackState;
 import android.media.tv.TvContentRating;
 import android.media.tv.TvInputManager;
 import android.media.tv.TvTrackInfo;
 import android.media.tv.TvView;
-import android.media.session.PlaybackState;
+import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.tv.dvr.data.RecordedProgram;
+
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-public class DvrPlayer {
+class DvrPlayer {
     private static final String TAG = "DvrPlayer";
     private static final boolean DEBUG = false;
 
@@ -47,12 +51,19 @@
     private long mInitialSeekPositionMs;
     private final TvView mTvView;
     private DvrPlayerCallback mCallback;
-    private AspectRatioChangedListener mAspectRatioChangedListener;
-    private ContentBlockedListener mContentBlockedListener;
+    private OnAspectRatioChangedListener mOnAspectRatioChangedListener;
+    private OnContentBlockedListener mOnContentBlockedListener;
+    private OnTracksAvailabilityChangedListener mOnTracksAvailabilityChangedListener;
+    private OnTrackSelectedListener mOnAudioTrackSelectedListener;
+    private OnTrackSelectedListener mOnSubtitleTrackSelectedListener;
+    private String mSelectedAudioTrackId;
+    private String mSelectedSubtitleTrackId;
     private float mAspectRatio = Float.NaN;
     private int mPlaybackState = PlaybackState.STATE_NONE;
     private long mTimeShiftCurrentPositionMs;
     private boolean mPauseOnPrepared;
+    private boolean mHasClosedCaption;
+    private boolean mHasMultiAudio;
     private final PlaybackParams mPlaybackParams = new PlaybackParams();
     private final DvrPlayerCallback mEmptyCallback = new DvrPlayerCallback();
     private long mStartPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
@@ -75,22 +86,40 @@
         public void onPlaybackEnded() { }
     }
 
-    public interface AspectRatioChangedListener {
+    public interface OnAspectRatioChangedListener {
         /**
          * Called when the Video's aspect ratio is changed.
+         *
+         * @param videoAspectRatio The aspect ratio of video. 0 stands for unknown ratios.
+         *                         Listeners should handle it carefully.
          */
         void onAspectRatioChanged(float videoAspectRatio);
     }
 
-    public interface ContentBlockedListener {
+    public interface OnContentBlockedListener {
         /**
          * Called when the Video's aspect ratio is changed.
          */
         void onContentBlocked(TvContentRating rating);
     }
 
+    public interface OnTracksAvailabilityChangedListener {
+        /**
+         * Called when the Video's subtitle or audio tracks are changed.
+         */
+        void onTracksAvailabilityChanged(boolean hasClosedCaption, boolean hasMultiAudio);
+    }
+
+    public interface OnTrackSelectedListener {
+        /**
+         * Called when certain subtitle or audio track is selected.
+         */
+        void onTrackSelected(String selectedTrackId);
+    }
+
     public DvrPlayer(TvView tvView) {
         mTvView = tvView;
+        mTvView.setCaptionEnabled(true);
         mPlaybackParams.setSpeed(1.0f);
         setTvViewCallbacks();
         setCallback(null);
@@ -236,6 +265,8 @@
         mTimeShiftCurrentPositionMs = 0;
         mPlaybackParams.setSpeed(1.0f);
         mProgram = null;
+        mSelectedAudioTrackId = null;
+        mSelectedSubtitleTrackId = null;
     }
 
     /**
@@ -250,17 +281,51 @@
     }
 
     /**
-     * Sets listener to aspect ratio changing.
+     * Sets the listener to aspect ratio changing.
      */
-    public void setAspectRatioChangedListener(AspectRatioChangedListener listener) {
-        mAspectRatioChangedListener = listener;
+    public void setOnAspectRatioChangedListener(OnAspectRatioChangedListener listener) {
+        mOnAspectRatioChangedListener = listener;
     }
 
     /**
-     * Sets listener to content blocking.
+     * Sets the listener to content blocking.
      */
-    public void setContentBlockedListener(ContentBlockedListener listener) {
-        mContentBlockedListener = listener;
+    public void setOnContentBlockedListener(OnContentBlockedListener listener) {
+        mOnContentBlockedListener = listener;
+    }
+
+    /**
+     * Sets the listener to tracks changing.
+     */
+    public void setOnTracksAvailabilityChangedListener(
+            OnTracksAvailabilityChangedListener listener) {
+        mOnTracksAvailabilityChangedListener = listener;
+    }
+
+    /**
+     * Sets the listener to tracks of the given type being selected.
+     *
+     * @param trackType should be either {@link TvTrackInfo#TYPE_AUDIO}
+     *                  or {@link TvTrackInfo#TYPE_SUBTITLE}.
+     */
+    public void setOnTrackSelectedListener(int trackType, OnTrackSelectedListener listener) {
+        if (trackType == TvTrackInfo.TYPE_AUDIO) {
+            mOnAudioTrackSelectedListener = listener;
+        } else if (trackType == TvTrackInfo.TYPE_SUBTITLE) {
+            mOnSubtitleTrackSelectedListener = listener;
+        }
+    }
+
+    /**
+     * Gets the listener to tracks of the given type being selected.
+     */
+    public OnTrackSelectedListener getOnTrackSelectedListener(int trackType) {
+        if (trackType == TvTrackInfo.TYPE_AUDIO) {
+            return mOnAudioTrackSelectedListener;
+        } else if (trackType == TvTrackInfo.TYPE_SUBTITLE) {
+            return mOnSubtitleTrackSelectedListener;
+        }
+        return null;
     }
 
     /**
@@ -306,6 +371,32 @@
     }
 
     /**
+     * Returns the subtitle tracks of the current playback.
+     */
+    public ArrayList<TvTrackInfo> getSubtitleTracks() {
+        return new ArrayList<>(mTvView.getTracks(TvTrackInfo.TYPE_SUBTITLE));
+    }
+
+    /**
+     * Returns the audio tracks of the current playback.
+     */
+    public ArrayList<TvTrackInfo> getAudioTracks() {
+        return new ArrayList<>(mTvView.getTracks(TvTrackInfo.TYPE_AUDIO));
+    }
+
+    /**
+     * Returns the ID of the selected track of the given type.
+     */
+    public String getSelectedTrackId(int trackType) {
+        if (trackType == TvTrackInfo.TYPE_AUDIO) {
+            return mSelectedAudioTrackId;
+        } else if (trackType == TvTrackInfo.TYPE_SUBTITLE) {
+            return mSelectedSubtitleTrackId;
+        }
+        return null;
+    }
+
+    /**
      * Returns if playback of the recorded program is started.
      */
     public boolean isPlaybackPrepared() {
@@ -313,6 +404,41 @@
                 && mPlaybackState != PlaybackState.STATE_CONNECTING;
     }
 
+    /**
+     * Selects the given track.
+     *
+     * @return ID of the selected track.
+     */
+    String selectTrack(int trackType, TvTrackInfo selectedTrack) {
+        String oldSelectedTrackId = getSelectedTrackId(trackType);
+        String newSelectedTrackId = selectedTrack == null ? null : selectedTrack.getId();
+        if (!TextUtils.equals(oldSelectedTrackId, newSelectedTrackId)) {
+            if (selectedTrack == null) {
+                mTvView.selectTrack(trackType, null);
+                return null;
+            } else {
+                List<TvTrackInfo> tracks = mTvView.getTracks(trackType);
+                if (tracks != null && tracks.contains(selectedTrack)) {
+                    mTvView.selectTrack(trackType, newSelectedTrackId);
+                    return newSelectedTrackId;
+                } else if (trackType == TvTrackInfo.TYPE_SUBTITLE && oldSelectedTrackId != null) {
+                    // Track not found, disabled closed caption.
+                    mTvView.selectTrack(trackType, null);
+                    return null;
+                }
+            }
+        }
+        return oldSelectedTrackId;
+    }
+
+    private void setSelectedTrackId(int trackType, String trackId) {
+        if (trackType == TvTrackInfo.TYPE_AUDIO) {
+            mSelectedAudioTrackId = trackId;
+        } else if (trackType == TvTrackInfo.TYPE_SUBTITLE) {
+            mSelectedSubtitleTrackId = trackId;
+        }
+    }
+
     private void setPlaybackSpeed(int speed) {
         mPlaybackParams.setSpeed(speed);
         mTvView.timeShiftSetPlaybackParams(mPlaybackParams);
@@ -369,28 +495,60 @@
                 if (status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE
                         && mPlaybackState == PlaybackState.STATE_CONNECTING) {
                     mTimeShiftPlayAvailable = true;
+                    if (mStartPositionMs != TvInputManager.TIME_SHIFT_INVALID_TIME) {
+                        // onTimeShiftStatusChanged is sometimes called after
+                        // onTimeShiftStartPositionChanged is called. In this case,
+                        // resumeToWatchedPositionIfNeeded needs to be called here.
+                        resumeToWatchedPositionIfNeeded();
+                    }
                 }
             }
 
             @Override
-            public void onTrackSelected(String inputId, int type, String trackId) {
-                if (trackId == null || type != TvTrackInfo.TYPE_VIDEO
-                        || mAspectRatioChangedListener == null) {
-                    return;
+            public void onTracksChanged(String inputId, List<TvTrackInfo> tracks) {
+                boolean hasClosedCaption =
+                        !mTvView.getTracks(TvTrackInfo.TYPE_SUBTITLE).isEmpty();
+                boolean hasMultiAudio = mTvView.getTracks(TvTrackInfo.TYPE_AUDIO).size() > 1;
+                if ((hasClosedCaption != mHasClosedCaption || hasMultiAudio != mHasMultiAudio)
+                        && mOnTracksAvailabilityChangedListener != null) {
+                    mOnTracksAvailabilityChangedListener
+                            .onTracksAvailabilityChanged(hasClosedCaption, hasMultiAudio);
                 }
-                List<TvTrackInfo> trackInfos = mTvView.getTracks(TvTrackInfo.TYPE_VIDEO);
-                if (trackInfos != null) {
-                    for (TvTrackInfo trackInfo : trackInfos) {
-                        if (trackInfo.getId().equals(trackId)) {
-                            float videoAspectRatio = trackInfo.getVideoPixelAspectRatio()
-                                    * trackInfo.getVideoWidth() / trackInfo.getVideoHeight();
-                            if (DEBUG) Log.d(TAG, "Aspect Ratio: " + videoAspectRatio);
-                            if (!Float.isNaN(videoAspectRatio)
-                                    && mAspectRatio != videoAspectRatio) {
-                                mAspectRatioChangedListener
-                                        .onAspectRatioChanged(videoAspectRatio);
-                                mAspectRatio = videoAspectRatio;
-                                return;
+                mHasClosedCaption = hasClosedCaption;
+                mHasMultiAudio = hasMultiAudio;
+            }
+
+            @Override
+            public void onTrackSelected(String inputId, int type, String trackId) {
+                if (type == TvTrackInfo.TYPE_AUDIO || type == TvTrackInfo.TYPE_SUBTITLE) {
+                    setSelectedTrackId(type, trackId);
+                    OnTrackSelectedListener listener = getOnTrackSelectedListener(type);
+                    if (listener != null) {
+                        listener.onTrackSelected(trackId);
+                    }
+                } else if (type == TvTrackInfo.TYPE_VIDEO && trackId != null
+                        && mOnAspectRatioChangedListener != null) {
+                    List<TvTrackInfo> trackInfos = mTvView.getTracks(TvTrackInfo.TYPE_VIDEO);
+                    if (trackInfos != null) {
+                        for (TvTrackInfo trackInfo : trackInfos) {
+                            if (trackInfo.getId().equals(trackId)) {
+                                float videoAspectRatio;
+                                int videoWidth = trackInfo.getVideoWidth();
+                                int videoHeight = trackInfo.getVideoHeight();
+                                if (videoWidth > 0 && videoHeight > 0) {
+                                    videoAspectRatio = trackInfo.getVideoPixelAspectRatio()
+                                            * trackInfo.getVideoWidth() / trackInfo.getVideoHeight();
+                                } else {
+                                    // Aspect ratio is unknown. Pass the message to listeners.
+                                    videoAspectRatio = 0;
+                                }
+                                if (DEBUG) Log.d(TAG, "Aspect Ratio: " + videoAspectRatio);
+                                if (mAspectRatio != videoAspectRatio || videoAspectRatio == 0) {
+                                    mOnAspectRatioChangedListener
+                                            .onAspectRatioChanged(videoAspectRatio);
+                                    mAspectRatio = videoAspectRatio;
+                                    return;
+                                }
                             }
                         }
                     }
@@ -399,8 +557,8 @@
 
             @Override
             public void onContentBlocked(String inputId, TvContentRating rating) {
-                if (mContentBlockedListener != null) {
-                    mContentBlockedListener.onContentBlocked(rating);
+                if (mOnContentBlockedListener != null) {
+                    mOnContentBlockedListener.onContentBlocked(rating);
                 }
             }
         });
diff --git a/src/com/android/tv/experiments/ExperimentFlag.java b/src/com/android/tv/experiments/ExperimentFlag.java
index 8f60c2b..c0cbd64 100644
--- a/src/com/android/tv/experiments/ExperimentFlag.java
+++ b/src/com/android/tv/experiments/ExperimentFlag.java
@@ -16,12 +16,19 @@
 
 package com.android.tv.experiments;
 
+import android.support.annotation.VisibleForTesting;
 
 /**
  * Experiments return values based on user, device and other criteria.
  */
 public final class ExperimentFlag<T> {
-    private final T mDefaultValue;
+
+    private static boolean sAllowOverrides = false;
+
+    @VisibleForTesting
+    public static void initForTest() {
+        sAllowOverrides = true;
+    }
 
     /** Returns a boolean experiment */
     public static ExperimentFlag<Boolean> createFlag(
@@ -30,6 +37,11 @@
                 defaultValue);
     }
 
+    private final T mDefaultValue;
+
+    private T mOverrideValue = null;
+    private boolean mOverridden = false;
+
     private ExperimentFlag(
             T defaultValue) {
         mDefaultValue = defaultValue;
@@ -37,6 +49,22 @@
 
     /** Returns value for this experiment */
     public T get() {
-        return mDefaultValue;
+        return sAllowOverrides && mOverridden ? mOverrideValue : mDefaultValue;
     }
+
+    @VisibleForTesting
+    public void override(T t) {
+        if (sAllowOverrides) {
+            mOverridden = true;
+            mOverrideValue = t;
+        }
+    }
+
+    @VisibleForTesting
+    public void resetOverride() {
+        mOverridden = false;
+    }
+
+
+
 }
diff --git a/src/com/android/tv/experiments/Experiments.java b/src/com/android/tv/experiments/Experiments.java
index f16c8d1..53cce97 100644
--- a/src/com/android/tv/experiments/Experiments.java
+++ b/src/com/android/tv/experiments/Experiments.java
@@ -23,12 +23,15 @@
 /**
  * Set of experiments visible in AOSP.
  *
- * <p>
- * This file is maintained by hand.
+ * <p>This file is maintained by hand.
  */
 public final class Experiments {
     public static final ExperimentFlag<Boolean> CLOUD_EPG = createFlag(
-            false);
+            true);
+
+    public static final ExperimentFlag<Boolean> ENABLE_UNRATED_CONTENT_SETTINGS =
+            createFlag(
+                    false);
 
     /**
      * Allow developer features such as the dev menu and other aids.
diff --git a/src/com/android/tv/guide/GenreListAdapter.java b/src/com/android/tv/guide/GenreListAdapter.java
index 2913599..ce19eb2 100644
--- a/src/com/android/tv/guide/GenreListAdapter.java
+++ b/src/com/android/tv/guide/GenreListAdapter.java
@@ -17,6 +17,7 @@
 package com.android.tv.guide;
 
 import android.content.Context;
+import android.support.annotation.MainThread;
 import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -32,7 +33,7 @@
 /**
  * Adapts the genre items obtained from {@link GenreItems} to the program guide side panel.
  */
-public class GenreListAdapter extends RecyclerView.Adapter<GenreListAdapter.GenreRowHolder> {
+class GenreListAdapter extends RecyclerView.Adapter<GenreListAdapter.GenreRowHolder> {
     private static final String TAG = "GenreListAdapter";
     private static final boolean DEBUG = false;
 
@@ -41,7 +42,7 @@
     private final ProgramGuide mProgramGuide;
     private String[] mGenreLabels;
 
-    public GenreListAdapter(Context context, ProgramManager programManager, ProgramGuide guide) {
+    GenreListAdapter(Context context, ProgramManager programManager, ProgramGuide guide) {
         mContext = context;
         mProgramManager = programManager;
         mProgramManager.addListener(new ProgramManager.ListenerAdapter() {
@@ -79,16 +80,28 @@
     @Override
     public GenreRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         View itemView = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
+        itemView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View view) {
+                // Animation is not meaningful now, skip it.
+                view.getStateListAnimator().jumpToCurrentState();
+            }
+
+            @Override
+            public void onViewDetachedFromWindow(View view) {
+                // Do nothing
+            }
+        });
         return new GenreRowHolder(itemView, mProgramGuide);
     }
 
-    public static class GenreRowHolder extends RecyclerView.ViewHolder implements
+    static class GenreRowHolder extends RecyclerView.ViewHolder implements
             View.OnFocusChangeListener {
         private final ProgramGuide mProgramGuide;
         private int mGenreId;
 
-        // Should be called from main thread.
-        public GenreRowHolder(View itemView, ProgramGuide programGuide) {
+        @MainThread
+        GenreRowHolder(View itemView, ProgramGuide programGuide) {
             super(itemView);
             mProgramGuide = programGuide;
         }
diff --git a/src/com/android/tv/guide/GuideUtils.java b/src/com/android/tv/guide/GuideUtils.java
index 5d11f06..403d00b 100644
--- a/src/com/android/tv/guide/GuideUtils.java
+++ b/src/com/android/tv/guide/GuideUtils.java
@@ -16,30 +16,38 @@
 
 package com.android.tv.guide;
 
+import android.graphics.Rect;
+import android.support.annotation.NonNull;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+
+import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 
-public class GuideUtils {
+class GuideUtils {
+    private static final int INVALID_INDEX = -1;
     private static int sWidthPerHour = 0;
 
     /**
      * Sets the width in pixels that corresponds to an hour in program guide.
      * Assume that this is called from main thread only, so, no synchronization.
      */
-    public static void setWidthPerHour(int widthPerHour) {
+    static void setWidthPerHour(int widthPerHour) {
         sWidthPerHour = widthPerHour;
     }
 
     /**
      * Gets the number of pixels in program guide table that corresponds to the given milliseconds.
      */
-    public static int convertMillisToPixel(long millis) {
+    static int convertMillisToPixel(long millis) {
         return (int) (millis * sWidthPerHour / TimeUnit.HOURS.toMillis(1));
     }
 
     /**
      * Gets the number of pixels in program guide table that corresponds to the given range.
      */
-    public static int convertMillisToPixel(long startMillis, long endMillis) {
+    static int convertMillisToPixel(long startMillis, long endMillis) {
         // Convert to pixels first to avoid accumulation of rounding errors.
         return GuideUtils.convertMillisToPixel(endMillis)
                 - GuideUtils.convertMillisToPixel(startMillis);
@@ -48,9 +56,101 @@
     /**
      * Gets the time in millis that corresponds to the given pixels in the program guide.
      */
-    public static long convertPixelToMillis(int pixel) {
+    static long convertPixelToMillis(int pixel) {
         return pixel * TimeUnit.HOURS.toMillis(1) / sWidthPerHour;
     }
 
+    /**
+     * Return the view should be focused in the given program row according to the focus range.
+
+     * @param keepCurrentProgramFocused If {@code true}, focuses on the current program if possible,
+     *                                  else falls back the general logic.
+     */
+    static View findNextFocusedProgram(View programRow, int focusRangeLeft,
+            int focusRangeRight, boolean keepCurrentProgramFocused) {
+        ArrayList<View> focusables = new ArrayList<>();
+        findFocusables(programRow, focusables);
+
+        if (keepCurrentProgramFocused) {
+            // Select the current program if possible.
+            for (int i = 0; i < focusables.size(); ++i) {
+                View focusable = focusables.get(i);
+                if (focusable instanceof ProgramItemView
+                        && isCurrentProgram((ProgramItemView) focusable)) {
+                    return focusable;
+                }
+            }
+        }
+
+        // Find the largest focusable among fully overlapped focusables.
+        int maxFullyOverlappedWidth = Integer.MIN_VALUE;
+        int maxPartiallyOverlappedWidth = Integer.MIN_VALUE;
+        int nextFocusIndex = INVALID_INDEX;
+        for (int i = 0; i < focusables.size(); ++i) {
+            View focusable = focusables.get(i);
+            Rect focusableRect = new Rect();
+            focusable.getGlobalVisibleRect(focusableRect);
+            if (focusableRect.left <= focusRangeLeft && focusRangeRight <= focusableRect.right) {
+                // the old focused range is fully inside the focusable, return directly.
+                return focusable;
+            } else if (focusRangeLeft <= focusableRect.left
+                    && focusableRect.right <= focusRangeRight) {
+                // the focusable is fully inside the old focused range, choose the widest one.
+                int width = focusableRect.width();
+                if (width > maxFullyOverlappedWidth) {
+                    nextFocusIndex = i;
+                    maxFullyOverlappedWidth = width;
+                }
+            } else if (maxFullyOverlappedWidth == Integer.MIN_VALUE) {
+                int overlappedWidth = (focusRangeLeft <= focusableRect.left) ?
+                        focusRangeRight - focusableRect.left
+                        : focusableRect.right - focusRangeLeft;
+                if (overlappedWidth > maxPartiallyOverlappedWidth) {
+                    nextFocusIndex = i;
+                    maxPartiallyOverlappedWidth = overlappedWidth;
+                }
+            }
+        }
+        if (nextFocusIndex != INVALID_INDEX) {
+            return focusables.get(nextFocusIndex);
+        }
+        return null;
+    }
+
+    /**
+     *  Returns {@code true} if the program displayed in the give
+     *  {@link com.android.tv.guide.ProgramItemView} is a current program.
+     */
+    static boolean isCurrentProgram(ProgramItemView view) {
+        return view.getTableEntry().isCurrentProgram();
+    }
+
+    /**
+     * Returns {@code true} if the given view is a descendant of the give container.
+     */
+    static boolean isDescendant(ViewGroup container, View view) {
+        if (view == null) {
+            return false;
+        }
+        for (ViewParent p = view.getParent(); p != null; p = p.getParent()) {
+            if (p == container) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static void findFocusables(View v, ArrayList<View> outFocusable) {
+        if (v.isFocusable()) {
+            outFocusable.add(v);
+        }
+        if (v instanceof ViewGroup) {
+            ViewGroup viewGroup = (ViewGroup) v;
+            for (int i = 0; i < viewGroup.getChildCount(); ++i) {
+                findFocusables(viewGroup.getChildAt(i), outFocusable);
+            }
+        }
+    }
+
     private GuideUtils() { }
 }
diff --git a/src/com/android/tv/guide/ProgramGrid.java b/src/com/android/tv/guide/ProgramGrid.java
index 77de582..5843642 100644
--- a/src/com/android/tv/guide/ProgramGrid.java
+++ b/src/com/android/tv/guide/ProgramGrid.java
@@ -20,17 +20,15 @@
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.support.v17.leanback.widget.VerticalGridView;
-import android.support.v7.widget.RecyclerView.LayoutManager;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Range;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 
 import com.android.tv.R;
 import com.android.tv.ui.OnRepeatedKeyInterceptListener;
 
-import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -52,7 +50,7 @@
                         clearUpDownFocusState(newFocus);
                     }
                     mNextFocusByUpDown = null;
-                    if (newFocus != ProgramGrid.this && contains(newFocus)) {
+                    if (GuideUtils.isDescendant(ProgramGrid.this, newFocus)) {
                         mLastFocusedView = newFocus;
                     }
                 }
@@ -90,8 +88,9 @@
 
     private View mLastFocusedView;
     private final Rect mTempRect = new Rect();
+    private int mLastUpDownDirection;
 
-    private boolean mKeepCurrentProgram;
+    private boolean mKeepCurrentProgramFocused;
 
     private ChildFocusListener mChildFocusListener;
     private final OnRepeatedKeyInterceptListener mOnRepeatedKeyInterceptListener;
@@ -132,21 +131,6 @@
         setOnKeyInterceptListener(mOnRepeatedKeyInterceptListener);
     }
 
-    /**
-     * Initializes ProgramGrid. It should be called before the view is actually attached to
-     * Window.
-     */
-    public void initialize(ProgramManager programManager) {
-        mProgramManager = programManager;
-    }
-
-    /**
-     * Registers a listener focus events occurring on children to the {@code ProgramGrid}.
-     */
-    public void setChildFocusListener(ChildFocusListener childFocusListener) {
-        mChildFocusListener = childFocusListener;
-    }
-
     @Override
     public void requestChildFocus(View child, View focused) {
         if (mChildFocusListener != null) {
@@ -173,11 +157,11 @@
     @Override
     public View focusSearch(View focused, int direction) {
         mNextFocusByUpDown = null;
-        if (focused == null || !contains(focused)) {
+        if (focused == null || (focused != this && !GuideUtils.isDescendant(this, focused))) {
             return super.focusSearch(focused, direction);
         }
         if (direction == View.FOCUS_UP || direction == View.FOCUS_DOWN) {
-            updateUpDownFocusState(focused);
+            updateUpDownFocusState(focused, direction);
             View nextFocus = focusFind(focused, direction);
             if (nextFocus != null) {
                 return nextFocus;
@@ -186,167 +170,6 @@
         return super.focusSearch(focused, direction);
     }
 
-    /**
-     * Resets focus states. If the logic to keep the last focus needs to be cleared, it should
-     * be called.
-     */
-    public void resetFocusState() {
-        mLastFocusedView = null;
-        clearUpDownFocusState(null);
-    }
-
-    private View focusFind(View focused, int direction) {
-        int focusedChildIndex = getFocusedChildIndex();
-        if (focusedChildIndex == INVALID_INDEX) {
-            Log.w(TAG, "No child view has focus");
-            return null;
-        }
-        int nextChildIndex = direction == View.FOCUS_UP ? focusedChildIndex - 1
-                : focusedChildIndex + 1;
-        if (nextChildIndex < 0 || nextChildIndex >= getChildCount()) {
-            return focused;
-        }
-        View nextChild = getChildAt(nextChildIndex);
-        ArrayList<View> focusables = new ArrayList<>();
-        findFocusables(nextChild, focusables);
-
-        int index = INVALID_INDEX;
-        if (mKeepCurrentProgram) {
-            // Select the current program if possible.
-            for (int i = 0; i < focusables.size(); ++i) {
-                View focusable = focusables.get(i);
-                if (!(focusable instanceof ProgramItemView)) {
-                    continue;
-                }
-                if (((ProgramItemView) focusable).getTableEntry().isCurrentProgram()) {
-                    index = i;
-                    break;
-                }
-            }
-            if (index != INVALID_INDEX) {
-                mNextFocusByUpDown = focusables.get(index);
-                return mNextFocusByUpDown;
-            } else {
-                mKeepCurrentProgram = false;
-            }
-        }
-
-        // Find the largest focusable among fully overlapped focusables.
-        int maxWidth = Integer.MIN_VALUE;
-        for (int i = 0; i < focusables.size(); ++i) {
-            View focusable = focusables.get(i);
-            Rect focusableRect = mTempRect;
-            focusable.getGlobalVisibleRect(focusableRect);
-            if (mFocusRangeLeft <= focusableRect.left && focusableRect.right <= mFocusRangeRight) {
-                int width = focusableRect.width();
-                if (width > maxWidth) {
-                    index = i;
-                    maxWidth = width;
-                }
-            } else if (focusableRect.left <= mFocusRangeLeft
-                    && mFocusRangeRight <= focusableRect.right) {
-                // focusableRect contains [mLeft, mRight].
-                index = i;
-                break;
-            }
-        }
-        if (index != INVALID_INDEX) {
-            mNextFocusByUpDown = focusables.get(index);
-            return mNextFocusByUpDown;
-        }
-
-        // Find the largest overlapped view among partially overlapped focusables.
-        maxWidth = Integer.MIN_VALUE;
-        for (int i = 0; i < focusables.size(); ++i) {
-            View focusable = focusables.get(i);
-            Rect focusableRect = mTempRect;
-            focusable.getGlobalVisibleRect(focusableRect);
-            if (mFocusRangeLeft <= focusableRect.left && focusableRect.left <= mFocusRangeRight) {
-                int overlappedWidth = mFocusRangeRight - focusableRect.left;
-                if (overlappedWidth > maxWidth) {
-                    index = i;
-                    maxWidth = overlappedWidth;
-                }
-            } else if (mFocusRangeLeft <= focusableRect.right
-                    && focusableRect.right <= mFocusRangeRight) {
-                int overlappedWidth = focusableRect.right - mFocusRangeLeft;
-                if (overlappedWidth > maxWidth) {
-                    index = i;
-                    maxWidth = overlappedWidth;
-                }
-            }
-        }
-        if (index != INVALID_INDEX) {
-            mNextFocusByUpDown = focusables.get(index);
-            return mNextFocusByUpDown;
-        }
-
-        Log.w(TAG, "focusFind doesn't find proper focusable");
-        return null;
-    }
-
-    // Returned value is not the position of VerticalGridView. But it's the index of ViewGroup
-    // among visible children.
-    private int getFocusedChildIndex() {
-        for (int i = 0; i < getChildCount(); ++i) {
-            if (getChildAt(i).hasFocus()) {
-                return i;
-            }
-        }
-        return INVALID_INDEX;
-    }
-
-    private void updateUpDownFocusState(View focused) {
-        int rightMostFocusablePosition = getRightMostFocusablePosition();
-        Rect focusedRect = mTempRect;
-
-        // In order to avoid from focusing small width item, we clip the position with
-        // mostRightFocusablePosition.
-        focused.getGlobalVisibleRect(focusedRect);
-        mFocusRangeLeft = Math.min(mFocusRangeLeft, rightMostFocusablePosition);
-        mFocusRangeRight = Math.min(mFocusRangeRight, rightMostFocusablePosition);
-        focusedRect.left = Math.min(focusedRect.left, rightMostFocusablePosition);
-        focusedRect.right = Math.min(focusedRect.right, rightMostFocusablePosition);
-
-        if (focusedRect.left > mFocusRangeRight || focusedRect.right < mFocusRangeLeft) {
-            Log.w(TAG, "The current focus is out of [mFocusRangeLeft, mFocusRangeRight]");
-            mFocusRangeLeft = focusedRect.left;
-            mFocusRangeRight = focusedRect.right;
-            return;
-        }
-        mFocusRangeLeft = Math.max(mFocusRangeLeft, focusedRect.left);
-        mFocusRangeRight = Math.min(mFocusRangeRight, focusedRect.right);
-    }
-
-    private void clearUpDownFocusState(View focus) {
-        mFocusRangeLeft = 0;
-        mFocusRangeRight = getRightMostFocusablePosition();
-        mNextFocusByUpDown = null;
-        mKeepCurrentProgram = focus != null && focus instanceof ProgramItemView
-                && ((ProgramItemView) focus).getTableEntry().isCurrentProgram();
-    }
-
-    private int getRightMostFocusablePosition() {
-        if (!getGlobalVisibleRect(mTempRect)) {
-            return Integer.MAX_VALUE;
-        }
-        return mTempRect.right - GuideUtils.convertMillisToPixel(FOCUS_AREA_RIGHT_MARGIN_MILLIS);
-    }
-
-    private boolean contains(View v) {
-        if (v == this) {
-            return true;
-        }
-        if (v == null || v == v.getRootView()) {
-            return false;
-        }
-        return contains((View) v.getParent());
-    }
-
-    public void onItemSelectionReset() {
-        getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
-    }
-
     @Override
     public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
         if (mLastFocusedView != null && mLastFocusedView.isShown()) {
@@ -383,6 +206,131 @@
         updateInputLogo();
     }
 
+    /**
+     * Initializes ProgramGrid. It should be called before the view is actually attached to
+     * Window.
+     */
+    void initialize(ProgramManager programManager) {
+        mProgramManager = programManager;
+    }
+
+    /**
+     * Registers a listener focus events occurring on children to the {@code ProgramGrid}.
+     */
+    void setChildFocusListener(ChildFocusListener childFocusListener) {
+        mChildFocusListener = childFocusListener;
+    }
+
+    void onItemSelectionReset() {
+        getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
+    }
+
+    /**
+     * Resets focus states. If the logic to keep the last focus needs to be cleared, it should
+     * be called.
+     */
+    void resetFocusState() {
+        mLastFocusedView = null;
+        clearUpDownFocusState(null);
+    }
+
+    /** Returns the currently focused item's horizontal range. */
+    Range<Integer> getFocusRange() {
+        return new Range<>(mFocusRangeLeft, mFocusRangeRight);
+    }
+
+    /** Returns if the next focused item should be the current program if possible. */
+    boolean isKeepCurrentProgramFocused() {
+        return mKeepCurrentProgramFocused;
+    }
+
+    /** Returns the last up/down move direction of browsing */
+    int getLastUpDownDirection() {
+        return mLastUpDownDirection;
+    }
+
+    private View focusFind(View focused, int direction) {
+        int focusedChildIndex = getFocusedChildIndex();
+        if (focusedChildIndex == INVALID_INDEX) {
+            Log.w(TAG, "No child view has focus");
+            return null;
+        }
+        int nextChildIndex = direction == View.FOCUS_UP ? focusedChildIndex - 1
+                : focusedChildIndex + 1;
+        if (nextChildIndex < 0 || nextChildIndex >= getChildCount()) {
+            // Wraparound if reached head or end
+            if (getSelectedPosition() == 0) {
+                scrollToPosition(getAdapter().getItemCount() - 1);
+                return null;
+            } else if (getSelectedPosition() == getAdapter().getItemCount() - 1) {
+                scrollToPosition(0);
+                return null;
+            }
+            return focused;
+        }
+        View nextFocusedProgram = GuideUtils.findNextFocusedProgram(getChildAt(nextChildIndex),
+                mFocusRangeLeft, mFocusRangeRight, mKeepCurrentProgramFocused);
+        if (nextFocusedProgram != null) {
+            nextFocusedProgram.getGlobalVisibleRect(mTempRect);
+            mNextFocusByUpDown = nextFocusedProgram;
+
+        } else {
+            Log.w(TAG, "focusFind doesn't find proper focusable");
+        }
+        return nextFocusedProgram;
+    }
+
+    // Returned value is not the position of VerticalGridView. But it's the index of ViewGroup
+    // among visible children.
+    private int getFocusedChildIndex() {
+        for (int i = 0; i < getChildCount(); ++i) {
+            if (getChildAt(i).hasFocus()) {
+                return i;
+            }
+        }
+        return INVALID_INDEX;
+    }
+
+    private void updateUpDownFocusState(View focused, int direction) {
+        mLastUpDownDirection = direction;
+        int rightMostFocusablePosition = getRightMostFocusablePosition();
+        Rect focusedRect = mTempRect;
+
+        // In order to avoid from focusing small width item, we clip the position with
+        // mostRightFocusablePosition.
+        focused.getGlobalVisibleRect(focusedRect);
+        mFocusRangeLeft = Math.min(mFocusRangeLeft, rightMostFocusablePosition);
+        mFocusRangeRight = Math.min(mFocusRangeRight, rightMostFocusablePosition);
+        focusedRect.left = Math.min(focusedRect.left, rightMostFocusablePosition);
+        focusedRect.right = Math.min(focusedRect.right, rightMostFocusablePosition);
+
+        if (focusedRect.left > mFocusRangeRight || focusedRect.right < mFocusRangeLeft) {
+            Log.w(TAG, "The current focus is out of [mFocusRangeLeft, mFocusRangeRight]");
+            mFocusRangeLeft = focusedRect.left;
+            mFocusRangeRight = focusedRect.right;
+            return;
+        }
+        mFocusRangeLeft = Math.max(mFocusRangeLeft, focusedRect.left);
+        mFocusRangeRight = Math.min(mFocusRangeRight, focusedRect.right);
+    }
+
+    private void clearUpDownFocusState(View focus) {
+        mLastUpDownDirection = 0;
+        mFocusRangeLeft = 0;
+        mFocusRangeRight = getRightMostFocusablePosition();
+        mNextFocusByUpDown = null;
+        // If focus is not a program item, drop focus to the current program when back to the grid
+        mKeepCurrentProgramFocused = !(focus instanceof ProgramItemView)
+                || GuideUtils.isCurrentProgram((ProgramItemView) focus);
+    }
+
+    private int getRightMostFocusablePosition() {
+        if (!getGlobalVisibleRect(mTempRect)) {
+            return Integer.MAX_VALUE;
+        }
+        return mTempRect.right - GuideUtils.convertMillisToPixel(FOCUS_AREA_RIGHT_MARGIN_MILLIS);
+    }
+
     private int getFirstVisibleChildIndex() {
         final LayoutManager mLayoutManager = getLayoutManager();
         int top = mLayoutManager.getPaddingTop();
@@ -398,7 +346,7 @@
         return -1;
     }
 
-    public void updateInputLogo() {
+    private void updateInputLogo() {
         int childCount = getChildCount();
         if (childCount == 0) {
             return;
@@ -409,25 +357,13 @@
         }
         View childView = getChildAt(firstVisibleChildIndex);
         int childAdapterPosition = getChildAdapterPosition(childView);
-        ((ProgramTableAdapter.ProgramRowHolder) getChildViewHolder(childView))
+        ((ProgramTableAdapter.ProgramRowViewHolder) getChildViewHolder(childView))
                 .updateInputLogo(childAdapterPosition, true);
         for (int i = firstVisibleChildIndex + 1; i < childCount; i++) {
             childView = getChildAt(i);
-            ((ProgramTableAdapter.ProgramRowHolder) getChildViewHolder(childView))
+            ((ProgramTableAdapter.ProgramRowViewHolder) getChildViewHolder(childView))
                     .updateInputLogo(childAdapterPosition, false);
             childAdapterPosition = getChildAdapterPosition(childView);
         }
     }
-
-    private static void findFocusables(View v, ArrayList<View> outFocusable) {
-        if (v.isFocusable()) {
-            outFocusable.add(v);
-        }
-        if (v instanceof ViewGroup) {
-            ViewGroup viewGroup = (ViewGroup) v;
-            for (int i = 0; i < viewGroup.getChildCount(); ++i) {
-                findFocusables(viewGroup.getChildAt(i), outFocusable);
-            }
-        }
-    }
 }
diff --git a/src/com/android/tv/guide/ProgramGuide.java b/src/com/android/tv/guide/ProgramGuide.java
index 120b3db..dd5444e 100644
--- a/src/com/android/tv/guide/ProgramGuide.java
+++ b/src/com/android/tv/guide/ProgramGuide.java
@@ -48,7 +48,7 @@
 import com.android.tv.Features;
 import com.android.tv.MainActivity;
 import com.android.tv.R;
-import com.android.tv.analytics.DurationTimer;
+import com.android.tv.util.DurationTimer;
 import com.android.tv.analytics.Tracker;
 import com.android.tv.common.WeakHandler;
 import com.android.tv.data.ChannelDataManager;
@@ -143,6 +143,7 @@
     private int mLastRequestedGenreId = GenreItems.ID_ALL_CHANNELS;
     private boolean mIsDuringResetRowSelection;
     private final Handler mHandler = new ProgramGuideHandler(this);
+    private boolean mActive;
 
     private final Runnable mHideRunnable = new Runnable() {
         @Override
@@ -217,7 +218,7 @@
                 .getDimensionPixelOffset(R.dimen.program_guide_side_panel_alignment_y));
         mSidePanelGridView.setWindowAlignmentOffsetPercent(
                 VerticalGridView.WINDOW_ALIGN_OFFSET_PERCENT_DISABLED);
-        // TODO: Remove this check when we ship TV with epg search enabled.
+
         if (Features.EPG_SEARCH.isEnabled(mActivity)) {
             mSearchOrb = (SearchOrbView) mContainer.findViewById(
                     R.id.program_guide_side_panel_search_orb);
@@ -250,8 +251,7 @@
                 res.getInteger(R.integer.max_recycled_view_pool_epg_header_row_item));
         mTimelineRow.setAdapter(mTimeListAdapter);
 
-        ProgramTableAdapter programTableAdapter = new ProgramTableAdapter(mActivity,
-                mProgramManager, this);
+        ProgramTableAdapter programTableAdapter = new ProgramTableAdapter(mActivity, this);
         programTableAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
             @Override
             public void onChanged() {
@@ -304,13 +304,6 @@
                 R.animator.program_guide_side_panel_enter_full,
                 0,
                 R.animator.program_guide_table_enter_full);
-        mShowAnimatorFull.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                ((ViewGroup) mSidePanel).setDescendantFocusability(
-                        ViewGroup.FOCUS_AFTER_DESCENDANTS);
-            }
-        });
 
         mShowAnimatorPartial = createAnimator(
                 R.animator.program_guide_side_panel_enter_partial,
@@ -383,34 +376,6 @@
                 || mSharedPreference.getBoolean(KEY_SHOW_GUIDE_PARTIAL, true);
     }
 
-    private void updateGuidePosition() {
-        // Align EPG at vertical center, if EPG table height is less than the screen size.
-        Resources res = mActivity.getResources();
-        int screenHeight = mContainer.getHeight();
-        if (screenHeight <= 0) {
-            // mContainer is not initialized yet.
-            return;
-        }
-        int startPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_margin_start);
-        int topPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_margin_top);
-        int bottomPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_margin_bottom);
-        int tableHeight = res.getDimensionPixelOffset(R.dimen.program_guide_table_header_row_height)
-                + mDetailHeight + mRowHeight * mGrid.getAdapter().getItemCount() + topPadding
-                + bottomPadding;
-        if (tableHeight > screenHeight) {
-            // EPG height is longer that the screen height.
-            mTable.setPaddingRelative(startPadding, topPadding, 0, 0);
-            LayoutParams layoutParams = mTable.getLayoutParams();
-            layoutParams.height = LayoutParams.WRAP_CONTENT;
-            mTable.setLayoutParams(layoutParams);
-        } else {
-            mTable.setPaddingRelative(startPadding, topPadding, 0, bottomPadding);
-            LayoutParams layoutParams = mTable.getLayoutParams();
-            layoutParams.height = tableHeight;
-            mTable.setLayoutParams(layoutParams);
-        }
-    }
-
     @Override
     public void onRequestChildFocus(View oldFocus, View newFocus) {
         if (oldFocus != null && newFocus != null) {
@@ -431,40 +396,6 @@
         }
     }
 
-    private Animator createAnimator(int sidePanelAnimResId, int sidePanelGridAnimResId,
-            int tableAnimResId) {
-        List<Animator> animatorList = new ArrayList<>();
-
-        Animator sidePanelAnimator = AnimatorInflater.loadAnimator(mActivity, sidePanelAnimResId);
-        sidePanelAnimator.setTarget(mSidePanel);
-        animatorList.add(sidePanelAnimator);
-
-        if (sidePanelGridAnimResId != 0) {
-            Animator sidePanelGridAnimator = AnimatorInflater.loadAnimator(mActivity,
-                    sidePanelGridAnimResId);
-            sidePanelGridAnimator.setTarget(mSidePanelGridView);
-            sidePanelGridAnimator.addListener(
-                    new HardwareLayerAnimatorListenerAdapter(mSidePanelGridView));
-            animatorList.add(sidePanelGridAnimator);
-        }
-        Animator tableAnimator = AnimatorInflater.loadAnimator(mActivity, tableAnimResId);
-        tableAnimator.setTarget(mTable);
-        tableAnimator.addListener(new HardwareLayerAnimatorListenerAdapter(mTable));
-        animatorList.add(tableAnimator);
-
-        AnimatorSet set = new AnimatorSet();
-        set.playTogether(animatorList);
-        return set;
-    }
-
-    /**
-     * Returns {@code true} if the program guide should process the input events.
-     */
-    public boolean isActive() {
-        return mContainer.getVisibility() == View.VISIBLE && !mHideAnimatorFull.isStarted()
-                && !mHideAnimatorPartial.isStarted();
-    }
-
     /**
      * Show the program guide.  This reveals the side panel, and the program guide table is shown
      * partially.
@@ -494,14 +425,11 @@
         mTimeListAdapter.update(mStartUtcTime);
         mTimelineRow.resetScroll();
 
-        if (!mShowGuidePartial) {
-            // Avoid changing focus from the genre side panel to the grid during animation.
-            // The descendant focus is changed to FOCUS_AFTER_DESCENDANTS after the animation.
-            ((ViewGroup) mSidePanel).setDescendantFocusability(
-                    ViewGroup.FOCUS_BLOCK_DESCENDANTS);
-        }
-
         mContainer.setVisibility(View.VISIBLE);
+        mActive = true;
+        if (!mShowGuidePartial) {
+            mTable.requestFocus();
+        }
         positionCurrentTimeIndicator();
         mSidePanelGridView.setSelectedPosition(0);
         if (DEBUG) {
@@ -536,13 +464,13 @@
                                 }
                             });
                 }
+                updateGuidePosition();
                 runnableAfterAnimatorReady.run();
                 if (mShowGuidePartial) {
                     mShowAnimatorPartial.start();
                 } else {
                     mShowAnimatorFull.start();
                 }
-                updateGuidePosition();
             }
         };
         mContainer.getViewTreeObserver().addOnGlobalLayoutListener(mOnLayoutListenerForShow);
@@ -564,7 +492,8 @@
         cancelHide();
         mProgramManager.programGuideVisibilityChanged(false);
         mProgramManager.removeListener(mProgramManagerListener);
-        if (isFull()) {
+        mActive = false;
+        if (!mShowGuidePartial) {
             mHideAnimatorFull.start();
         } else {
             mHideAnimatorPartial.start();
@@ -587,50 +516,21 @@
         }
     }
 
+    /**
+     * Schedules hiding the program guide.
+     */
     public void scheduleHide() {
         cancelHide();
         mHandler.postDelayed(mHideRunnable, mShowDurationMillis);
     }
 
     /**
-     * Returns the scroll offset of the time line row in pixels.
-     */
-    public int getTimelineRowScrollOffset() {
-        return mTimelineRow.getScrollOffset();
-    }
-
-    /**
-     * Cancel hiding the program guide.
+     * Cancels hiding the program guide.
      */
     public void cancelHide() {
         mHandler.removeCallbacks(mHideRunnable);
     }
 
-    // Returns if program table is full screen mode.
-    private boolean isFull() {
-        return mPartialToFullAnimator.isStarted() || mTable.getTranslationX() == 0;
-    }
-
-    private void startFull() {
-        if (isFull() || mAccessibilityManager.isEnabled()) {
-            // If accessibility service is enabled, focus cannot be moved to side panel due to it's
-            // hidden. Therefore, we don't hide side panel when accessibility service is enabled.
-            return;
-        }
-        mShowGuidePartial = false;
-        mSharedPreference.edit().putBoolean(KEY_SHOW_GUIDE_PARTIAL, mShowGuidePartial).apply();
-        mPartialToFullAnimator.start();
-    }
-
-    private void startPartial() {
-        if (!isFull()) {
-            return;
-        }
-        mShowGuidePartial = true;
-        mSharedPreference.edit().putBoolean(KEY_SHOW_GUIDE_PARTIAL, mShowGuidePartial).apply();
-        mFullToPartialAnimator.start();
-    }
-
     /**
      * Process the {@code KEYCODE_BACK} key event.
      */
@@ -639,16 +539,30 @@
     }
 
     /**
-     * Gets {@link VerticalGridView} for "genre select" side panel.
+     * Returns {@code true} if the program guide should process the input events.
      */
-    public VerticalGridView getSidePanel() {
-        return mSidePanelGridView;
+    public boolean isActive() {
+        return mActive;
+    }
+
+    /**
+     * Returns {@code true} if the program guide is shown, i.e. showing animation is done and
+     * hiding animation is not started yet.
+     */
+    public boolean isRunningAnimation() {
+        return mShowAnimatorPartial.isStarted() || mShowAnimatorFull.isStarted()
+                || mHideAnimatorPartial.isStarted() || mHideAnimatorFull.isStarted();
+    }
+
+    /** Returns if program table is in full screen mode. **/
+    boolean isFull() {
+        return !mShowGuidePartial;
     }
 
     /**
      * Requests change genre to {@code genreId}.
      */
-    public void requestGenreChange(int genreId) {
+    void requestGenreChange(int genreId) {
         if (mLastRequestedGenreId == genreId) {
             // When Recycler.onLayout() removes its children to recycle,
             // View tries to find next focus candidate immediately
@@ -679,6 +593,104 @@
         mProgramTableFadeOutAnimator.start();
     }
 
+    /**
+     * Returns the scroll offset of the time line row in pixels.
+     */
+    int getTimelineRowScrollOffset() {
+        return mTimelineRow.getScrollOffset();
+    }
+
+    /** Returns the program grid view that hold all component views. */
+    ProgramGrid getProgramGrid() {
+        return mGrid;
+    }
+
+    /**
+     * Gets {@link VerticalGridView} for "genre select" side panel.
+     */
+    VerticalGridView getSidePanel() {
+        return mSidePanelGridView;
+    }
+
+    /** Returns the program manager the program guide is using to provide program information. */
+    ProgramManager getProgramManager() {
+        return mProgramManager;
+    }
+
+    private void updateGuidePosition() {
+        // Align EPG at vertical center, if EPG table height is less than the screen size.
+        Resources res = mActivity.getResources();
+        int screenHeight = mContainer.getHeight();
+        if (screenHeight <= 0) {
+            // mContainer is not initialized yet.
+            return;
+        }
+        int startPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_margin_start);
+        int topPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_margin_top);
+        int bottomPadding = res.getDimensionPixelOffset(R.dimen.program_guide_table_margin_bottom);
+        int tableHeight = res.getDimensionPixelOffset(R.dimen.program_guide_table_header_row_height)
+                + mDetailHeight + mRowHeight * mGrid.getAdapter().getItemCount() + topPadding
+                + bottomPadding;
+        if (tableHeight > screenHeight) {
+            // EPG height is longer that the screen height.
+            mTable.setPaddingRelative(startPadding, topPadding, 0, 0);
+            LayoutParams layoutParams = mTable.getLayoutParams();
+            layoutParams.height = LayoutParams.WRAP_CONTENT;
+            mTable.setLayoutParams(layoutParams);
+        } else {
+            mTable.setPaddingRelative(startPadding, topPadding, 0, bottomPadding);
+            LayoutParams layoutParams = mTable.getLayoutParams();
+            layoutParams.height = tableHeight;
+            mTable.setLayoutParams(layoutParams);
+        }
+    }
+
+    private Animator createAnimator(int sidePanelAnimResId, int sidePanelGridAnimResId,
+            int tableAnimResId) {
+        List<Animator> animatorList = new ArrayList<>();
+
+        Animator sidePanelAnimator = AnimatorInflater.loadAnimator(mActivity, sidePanelAnimResId);
+        sidePanelAnimator.setTarget(mSidePanel);
+        animatorList.add(sidePanelAnimator);
+
+        if (sidePanelGridAnimResId != 0) {
+            Animator sidePanelGridAnimator = AnimatorInflater.loadAnimator(mActivity,
+                    sidePanelGridAnimResId);
+            sidePanelGridAnimator.setTarget(mSidePanelGridView);
+            sidePanelGridAnimator.addListener(
+                    new HardwareLayerAnimatorListenerAdapter(mSidePanelGridView));
+            animatorList.add(sidePanelGridAnimator);
+        }
+        Animator tableAnimator = AnimatorInflater.loadAnimator(mActivity, tableAnimResId);
+        tableAnimator.setTarget(mTable);
+        tableAnimator.addListener(new HardwareLayerAnimatorListenerAdapter(mTable));
+        animatorList.add(tableAnimator);
+
+        AnimatorSet set = new AnimatorSet();
+        set.playTogether(animatorList);
+        return set;
+    }
+
+    private void startFull() {
+        if (!mShowGuidePartial || mAccessibilityManager.isEnabled()) {
+            // If accessibility service is enabled, focus cannot be moved to side panel due to it's
+            // hidden. Therefore, we don't hide side panel when accessibility service is enabled.
+            return;
+        }
+        mShowGuidePartial = false;
+        mSharedPreference.edit().putBoolean(KEY_SHOW_GUIDE_PARTIAL, mShowGuidePartial).apply();
+        mPartialToFullAnimator.start();
+    }
+
+    private void startPartial() {
+        if (mShowGuidePartial) {
+            return;
+        }
+        mShowGuidePartial = true;
+        mSharedPreference.edit().putBoolean(KEY_SHOW_GUIDE_PARTIAL, mShowGuidePartial).apply();
+        mFullToPartialAnimator.start();
+    }
+
     private void startCurrentTimeIndicator(long initialDelay) {
         mHandler.postDelayed(mUpdateTimeIndicator, initialDelay);
     }
@@ -775,10 +787,12 @@
             mDetailInAnimator.cancel();
         }
 
-        int direction = 0;
-        if (outRow != null && inRow != null) {
-            // -1 means the selection goes downwards and 1 goes upwards
-            direction = outRow.getTop() < inRow.getTop() ? -1 : 1;
+        int operationDirection = mGrid.getLastUpDownDirection();
+        int animationPadding = 0;
+        if (operationDirection == View.FOCUS_UP) {
+            animationPadding = mDetailPadding;
+        } else if (operationDirection == View.FOCUS_DOWN) {
+            animationPadding = -mDetailPadding;
         }
 
         View outDetail = outRow != null ? outRow.findViewById(R.id.detail) : null;
@@ -788,7 +802,7 @@
             Animator fadeOutAnimator = ObjectAnimator.ofPropertyValuesHolder(outDetailContent,
                     PropertyValuesHolder.ofFloat(View.ALPHA, outDetail.getAlpha(), 0f),
                     PropertyValuesHolder.ofFloat(View.TRANSLATION_Y,
-                            outDetailContent.getTranslationY(), direction * mDetailPadding));
+                            outDetailContent.getTranslationY(), animationPadding));
             fadeOutAnimator.setStartDelay(0);
             fadeOutAnimator.setDuration(mAnimationDuration);
             fadeOutAnimator.addListener(new HardwareLayerAnimatorListenerAdapter(outDetailContent));
@@ -842,8 +856,7 @@
             });
             Animator fadeInAnimator = ObjectAnimator.ofPropertyValuesHolder(inDetailContent,
                     PropertyValuesHolder.ofFloat(View.ALPHA, 0f, 1f),
-                    PropertyValuesHolder.ofFloat(View.TRANSLATION_Y,
-                            direction * -mDetailPadding, 0f));
+                    PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, -animationPadding, 0f));
             fadeInAnimator.setDuration(mAnimationDuration);
             fadeInAnimator.addListener(new HardwareLayerAnimatorListenerAdapter(inDetailContent));
 
@@ -910,7 +923,7 @@
     }
 
     private static class ProgramGuideHandler extends WeakHandler<ProgramGuide> {
-        public ProgramGuideHandler(ProgramGuide ref) {
+        ProgramGuideHandler(ProgramGuide ref) {
             super(ref);
         }
 
diff --git a/src/com/android/tv/guide/ProgramItemView.java b/src/com/android/tv/guide/ProgramItemView.java
index 4c7a440..b23d578 100644
--- a/src/com/android/tv/guide/ProgramItemView.java
+++ b/src/com/android/tv/guide/ProgramItemView.java
@@ -44,8 +44,8 @@
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.data.Channel;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.guide.ProgramManager.TableEntry;
 import com.android.tv.util.ToastUtils;
 import com.android.tv.util.Utils;
@@ -73,6 +73,7 @@
     private static TextAppearanceSpan sEpisodeTitleStyle;
     private static TextAppearanceSpan sGrayedOutEpisodeTitleStyle;
 
+    private ProgramGuide mProgramGuide;
     private DvrManager mDvrManager;
     private TableEntry mTableEntry;
     private int mMaxWidthForRipple;
@@ -106,18 +107,19 @@
                 }, entry.getWidth() > ((ProgramItemView) view).mMaxWidthForRipple ? 0
                         : view.getResources()
                                 .getInteger(R.integer.program_guide_ripple_anim_duration));
-            } else if (CommonFeatures.DVR.isEnabled(view.getContext())) {
+            } else if (entry.program != null && CommonFeatures.DVR.isEnabled(view.getContext())) {
                 DvrManager dvrManager = singletons.getDvrManager();
                 if (entry.entryStartUtcMillis > System.currentTimeMillis()
                         && dvrManager.isProgramRecordable(entry.program)) {
                     if (entry.scheduledRecording == null) {
-                        if (DvrUiHelper.checkStorageStatusAndShowErrorMessage(tvActivity,
-                                channel.getInputId())
-                                && DvrUiHelper.handleCreateSchedule(tvActivity, entry.program)) {
-                            String msg = view.getContext().getString(
-                                    R.string.dvr_msg_program_scheduled, entry.program.getTitle());
-                            ToastUtils.show(view.getContext(), msg, Toast.LENGTH_SHORT);
-                        }
+                        DvrUiHelper.checkStorageStatusAndShowErrorMessage(tvActivity,
+                                channel.getInputId(), new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        DvrUiHelper.requestRecordingFutureProgram(tvActivity,
+                                                entry.program, false);
+                                    }
+                                });
                     } else {
                         dvrManager.removeScheduledRecording(entry.scheduledRecording);
                         String msg = view.getResources().getString(
@@ -158,6 +160,11 @@
             }
             if (entry.isCurrentProgram()) {
                 Drawable background = getBackground();
+                if (!mProgramGuide.isActive() || mProgramGuide.isRunningAnimation()) {
+                    // If program guide is not active or is during showing/hiding,
+                    // the animation is unnecessary, skip it.
+                    background.jumpToCurrentState();
+                }
                 int progress = getProgress(entry.entryStartUtcMillis, entry.entryEndUtcMillis);
                 setProgress(background, R.id.reverse_progress, MAX_PROGRESS - progress);
             }
@@ -247,8 +254,9 @@
     }
 
     @SuppressLint("SwitchIntDef")
-    public void setValues(TableEntry entry, int selectedGenreId, long fromUtcMillis,
-            long toUtcMillis, String gapTitle) {
+    public void setValues(ProgramGuide programGuide, TableEntry entry, int selectedGenreId,
+            long fromUtcMillis, long toUtcMillis, String gapTitle) {
+        mProgramGuide = programGuide;
         mTableEntry = entry;
 
         ViewGroup.LayoutParams layoutParams = getLayoutParams();
@@ -376,6 +384,7 @@
         }
 
         setTag(null);
+        mProgramGuide = null;
         mTableEntry = null;
     }
 
diff --git a/src/com/android/tv/guide/ProgramListAdapter.java b/src/com/android/tv/guide/ProgramListAdapter.java
index 03aea5a..c1fcdd4 100644
--- a/src/com/android/tv/guide/ProgramListAdapter.java
+++ b/src/com/android/tv/guide/ProgramListAdapter.java
@@ -32,11 +32,12 @@
  * Adapts a program list for a specific channel from {@link ProgramManager} to a row of the program
  * guide table.
  */
-public class ProgramListAdapter extends RecyclerView.Adapter<ProgramListAdapter.ProgramViewHolder>
+class ProgramListAdapter extends RecyclerView.Adapter<ProgramListAdapter.ProgramItemViewHolder>
         implements TableEntriesUpdatedListener {
     private static final String TAG = "ProgramListAdapter";
     private static final boolean DEBUG = false;
 
+    private final ProgramGuide mProgramGuide;
     private final ProgramManager mProgramManager;
     private final int mChannelIndex;
     private final String mNoInfoProgramTitle;
@@ -44,9 +45,10 @@
 
     private long mChannelId;
 
-    public ProgramListAdapter(Resources res, ProgramManager programManager, int channelIndex) {
+    ProgramListAdapter(Resources res, ProgramGuide programGuide, int channelIndex) {
         setHasStableIds(true);
-        mProgramManager = programManager;
+        mProgramGuide = programGuide;
+        mProgramManager = programGuide.getProgramManager();
         mChannelIndex = channelIndex;
         mNoInfoProgramTitle = res.getString(R.string.program_title_for_no_information);
         mBlockedProgramTitle = res.getString(R.string.program_title_for_blocked_channel);
@@ -65,10 +67,6 @@
         }
     }
 
-    public ProgramManager getProgramManager() {
-        return mProgramManager;
-    }
-
     @Override
     public int getItemCount() {
         return mProgramManager.getTableEntryCount(mChannelId);
@@ -85,38 +83,40 @@
     }
 
     @Override
-    public void onBindViewHolder(ProgramViewHolder holder, int position) {
+    public void onBindViewHolder(ProgramItemViewHolder holder, int position) {
         TableEntry tableEntry = mProgramManager.getTableEntry(mChannelId, position);
         String gapTitle = tableEntry.isBlocked() ? mBlockedProgramTitle : mNoInfoProgramTitle;
-        holder.onBind(tableEntry, this.getProgramManager(), gapTitle);
+        holder.onBind(tableEntry, mProgramGuide, gapTitle);
     }
 
     @Override
-    public void onViewRecycled(ProgramViewHolder holder) {
+    public void onViewRecycled(ProgramItemViewHolder holder) {
         holder.onUnbind();
     }
 
     @Override
-    public ProgramViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+    public ProgramItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         View itemView = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
-        return new ProgramViewHolder(itemView);
+        return new ProgramItemViewHolder(itemView);
     }
 
-    public static class ProgramViewHolder extends RecyclerView.ViewHolder {
+    static class ProgramItemViewHolder extends RecyclerView.ViewHolder {
         // Should be called from main thread.
-        public ProgramViewHolder(View itemView) {
+        ProgramItemViewHolder(View itemView) {
             super(itemView);
         }
 
-        public void onBind(TableEntry entry, ProgramManager programManager, String gapTitle) {
+        void onBind(TableEntry entry, ProgramGuide programGuide, String gapTitle) {
             if (DEBUG) {
                 Log.d(TAG, "onBind. View = " + itemView + ", Entry = " + entry);
             }
-            ((ProgramItemView) itemView).setValues(entry, programManager.getSelectedGenreId(),
-                    programManager.getFromUtcMillis(), programManager.getToUtcMillis(), gapTitle);
+            ProgramManager programManager = programGuide.getProgramManager();
+            ((ProgramItemView) itemView).setValues(programGuide, entry,
+                    programManager.getSelectedGenreId(), programManager.getFromUtcMillis(),
+                    programManager.getToUtcMillis(), gapTitle);
         }
 
-        public void onUnbind() {
+        void onUnbind() {
             ((ProgramItemView) itemView).clearValues();
         }
     }
diff --git a/src/com/android/tv/guide/ProgramManager.java b/src/com/android/tv/guide/ProgramManager.java
index e3d919d..4ec3f77 100644
--- a/src/com/android/tv/guide/ProgramManager.java
+++ b/src/com/android/tv/guide/ProgramManager.java
@@ -29,7 +29,7 @@
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrScheduleManager;
 import com.android.tv.dvr.DvrScheduleManager.OnConflictStateChangeListener;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.util.TvInputManagerHelper;
 import com.android.tv.util.Utils;
 
@@ -68,107 +68,6 @@
     private long mFromUtcMillis;
     private long mToUtcMillis;
 
-    /**
-     * Entry for program guide table. An "entry" can be either an actual program or a gap between
-     * programs. This is needed for {@link ProgramListAdapter} because
-     * {@link android.support.v17.leanback.widget.HorizontalGridView} ignores margins between items.
-     */
-    public static class TableEntry {
-        /** Channel ID which this entry is included. */
-        public final long channelId;
-
-        /** Program corresponding to the entry. {@code null} means that this entry is a gap. */
-        public final Program program;
-
-        public final ScheduledRecording scheduledRecording;
-
-        /** Start time of entry in UTC milliseconds. */
-        public final long entryStartUtcMillis;
-
-        /** End time of entry in UTC milliseconds */
-        public final long entryEndUtcMillis;
-
-        private final boolean mIsBlocked;
-
-        private TableEntry(long channelId, long startUtcMillis, long endUtcMillis) {
-            this(channelId, null, startUtcMillis, endUtcMillis, false);
-        }
-
-        private TableEntry(long channelId, long startUtcMillis, long endUtcMillis,
-                boolean blocked) {
-            this(channelId, null, null, startUtcMillis, endUtcMillis, blocked);
-        }
-
-        private TableEntry(long channelId, Program program, long entryStartUtcMillis,
-                long entryEndUtcMillis, boolean isBlocked) {
-            this(channelId, program, null, entryStartUtcMillis, entryEndUtcMillis, isBlocked);
-        }
-
-        private TableEntry(long channelId, Program program, ScheduledRecording scheduledRecording,
-                long entryStartUtcMillis, long entryEndUtcMillis, boolean isBlocked) {
-            this.channelId = channelId;
-            this.program = program;
-            this.scheduledRecording = scheduledRecording;
-            this.entryStartUtcMillis = entryStartUtcMillis;
-            this.entryEndUtcMillis = entryEndUtcMillis;
-            mIsBlocked = isBlocked;
-        }
-
-        /**
-         * A stable id useful for {@link android.support.v7.widget.RecyclerView.Adapter}.
-         */
-        public long getId() {
-            // using a negative entryEndUtcMillis keeps it from conflicting with program Id
-            return program != null ? program.getId() : -entryEndUtcMillis;
-        }
-
-        /**
-         * Returns true if this is a gap.
-         */
-        public boolean isGap() {
-            return !Program.isValid(program);
-        }
-
-        /**
-         * Returns true if this channel is blocked.
-         */
-        public boolean isBlocked() {
-            return mIsBlocked;
-        }
-
-        /**
-         * Returns true if this program is on the air.
-         */
-        public boolean isCurrentProgram() {
-            long current = System.currentTimeMillis();
-            return entryStartUtcMillis <= current && entryEndUtcMillis > current;
-        }
-
-        /**
-         * Returns if this program has the genre.
-         */
-        public boolean hasGenre(int genreId) {
-            return !isGap() && program.hasGenre(genreId);
-        }
-
-        /**
-         * Returns the width of table entry, in pixels.
-         */
-        public int getWidth() {
-            return GuideUtils.convertMillisToPixel(entryStartUtcMillis, entryEndUtcMillis);
-        }
-
-        @Override
-        public String toString() {
-            return "TableEntry{"
-                    + "hashCode=" + hashCode()
-                    + ", channelId=" + channelId
-                    + ", program=" + program
-                    + ", startTime=" + Utils.toTimeString(entryStartUtcMillis)
-                    + ", endTimeTime=" + Utils.toTimeString(entryEndUtcMillis) + "}";
-        }
-    }
-
     private List<Channel> mChannels = new ArrayList<>();
     private final Map<Long, List<TableEntry>> mChannelIdEntriesMap = new HashMap<>();
     private final List<List<Channel>> mGenreChannelList = new ArrayList<>();
@@ -293,7 +192,7 @@
         mDvrScheduleManager = dvrScheduleManager;
     }
 
-    public void programGuideVisibilityChanged(boolean visible) {
+    void programGuideVisibilityChanged(boolean visible) {
         mProgramDataManager.setPauseProgramUpdate(visible);
         if (visible) {
             mChannelDataManager.addListener(mChannelDataManagerListener);
@@ -325,87 +224,51 @@
     /**
      * Adds a {@link Listener}.
      */
-    public void addListener(Listener listener) {
+    void addListener(Listener listener) {
         mListeners.add(listener);
     }
 
     /**
      * Registers a listener to be invoked when table entries are updated.
      */
-    public void addTableEntriesUpdatedListener(TableEntriesUpdatedListener listener) {
+    void addTableEntriesUpdatedListener(TableEntriesUpdatedListener listener) {
         mTableEntriesUpdatedListeners.add(listener);
     }
 
     /**
      * Registers a listener to be invoked when a table entry is changed.
      */
-    public void addTableEntryChangedListener(TableEntryChangedListener listener) {
+    void addTableEntryChangedListener(TableEntryChangedListener listener) {
         mTableEntryChangedListeners.add(listener);
     }
 
     /**
      * Removes a {@link Listener}.
      */
-    public void removeListener(Listener listener) {
+    void removeListener(Listener listener) {
         mListeners.remove(listener);
     }
 
     /**
      * Removes a previously installed table entries update listener.
      */
-    public void removeTableEntriesUpdatedListener(TableEntriesUpdatedListener listener) {
+    void removeTableEntriesUpdatedListener(TableEntriesUpdatedListener listener) {
         mTableEntriesUpdatedListeners.remove(listener);
     }
 
     /**
      * Removes a previously installed table entry changed listener.
      */
-    public void removeTableEntryChangedListener(TableEntryChangedListener listener) {
+    void removeTableEntryChangedListener(TableEntryChangedListener listener) {
         mTableEntryChangedListeners.remove(listener);
     }
 
     /**
-     * Build genre filters based on the current programs.
-     * This categories channels by its current program's canonical genres
-     * and subsequent @{link resetChannelListWithGenre(int)} calls will reset channel list
-     * with built channel list.
-     * This is expected to be called whenever program guide is shown.
-     */
-    public void buildGenreFilters() {
-        if (DEBUG) Log.d(TAG, "buildGenreFilters");
-
-        mGenreChannelList.clear();
-        for (int i = 0; i < GenreItems.getGenreCount(); i++) {
-            mGenreChannelList.add(new ArrayList<>());
-        }
-        for (Channel channel : mChannels) {
-            // TODO: Use programs in visible area instead of using current programs only.
-            Program currentProgram = mProgramDataManager.getCurrentProgram(channel.getId());
-            if (currentProgram != null && currentProgram.getCanonicalGenres() != null) {
-                for (String genre : currentProgram.getCanonicalGenres()) {
-                    mGenreChannelList.get(GenreItems.getId(genre)).add(channel);
-                }
-            }
-        }
-        mGenreChannelList.set(GenreItems.ID_ALL_CHANNELS, mChannels);
-        mFilteredGenreIds.clear();
-        mFilteredGenreIds.add(0);
-        for (int i = 1; i < GenreItems.getGenreCount(); i++) {
-            if (mGenreChannelList.get(i).size() > 0) {
-                mFilteredGenreIds.add(i);
-            }
-        }
-        mSelectedGenreId = GenreItems.ID_ALL_CHANNELS;
-        mFilteredChannels = mChannels;
-        notifyGenresUpdated();
-    }
-
-    /**
      * Resets channel list with given genre.
      * Caller should call {@link #buildGenreFilters()} prior to call this API to make
      * This notifies channel updates to listeners.
      */
-    public void resetChannelListWithGenre(int genreId) {
+    void resetChannelListWithGenre(int genreId) {
         if (genreId == mSelectedGenreId) {
             return;
         }
@@ -422,13 +285,154 @@
     }
 
     /**
+     * Update the initial time range to manage. It updates program entries and genre as well.
+     */
+    void updateInitialTimeRange(long startUtcMillis, long endUtcMillis) {
+        mStartUtcMillis = startUtcMillis;
+        if (endUtcMillis > mEndUtcMillis) {
+            mEndUtcMillis = endUtcMillis;
+        }
+
+        mProgramDataManager.setPrefetchTimeRange(mStartUtcMillis);
+        updateChannels(true);
+        setTimeRange(startUtcMillis, endUtcMillis);
+    }
+
+
+    /**
+     * Shifts the time range by the given time. Also makes ProgramGuide scroll the views.
+     */
+    void shiftTime(long timeMillisToScroll) {
+        long fromUtcMillis = mFromUtcMillis + timeMillisToScroll;
+        long toUtcMillis = mToUtcMillis + timeMillisToScroll;
+        if (fromUtcMillis < mStartUtcMillis) {
+            fromUtcMillis = mStartUtcMillis;
+            toUtcMillis += mStartUtcMillis - fromUtcMillis;
+        }
+        if (toUtcMillis > mEndUtcMillis) {
+            fromUtcMillis -= toUtcMillis - mEndUtcMillis;
+            toUtcMillis = mEndUtcMillis;
+        }
+        setTimeRange(fromUtcMillis, toUtcMillis);
+    }
+
+    /**
+     * Returned the scrolled(shifted) time in milliseconds.
+     */
+    long getShiftedTime() {
+        return mFromUtcMillis - mStartUtcMillis;
+    }
+
+    /**
+     * Returns the start time set by {@link #updateInitialTimeRange}.
+     */
+    long getStartTime() {
+        return mStartUtcMillis;
+    }
+
+    /**
+     * Returns the program index of the program with {@code entryId} or -1 if not found.
+     */
+    int getProgramIdIndex(long channelId, long entryId) {
+        List<TableEntry> entries = mChannelIdEntriesMap.get(channelId);
+        if (entries != null) {
+            for (int i = 0; i < entries.size(); i++) {
+                if (entries.get(i).getId() == entryId) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Returns the program index of the program at {@code time} or -1 if not found.
+     */
+    int getProgramIndexAtTime(long channelId, long time) {
+        List<TableEntry> entries = mChannelIdEntriesMap.get(channelId);
+        for (int i = 0; i < entries.size(); ++i) {
+            TableEntry entry = entries.get(i);
+            if (entry.entryStartUtcMillis <= time
+                    && time < entry.entryEndUtcMillis) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Returns the start time of currently managed time range, in UTC millisecond.
+     */
+    long getFromUtcMillis() {
+        return mFromUtcMillis;
+    }
+
+    /**
+     * Returns the end time of currently managed time range, in UTC millisecond.
+     */
+    long getToUtcMillis() {
+        return mToUtcMillis;
+    }
+
+    /**
+     * Returns the number of the currently managed channels.
+     */
+    int getChannelCount() {
+        return mFilteredChannels.size();
+    }
+
+    /**
+     * Returns a {@link Channel} at a given {@code channelIndex} of the currently managed channels.
+     * Returns {@code null} if such a channel is not found.
+     */
+    Channel getChannel(int channelIndex) {
+        if (channelIndex < 0 || channelIndex >= getChannelCount()) {
+            return null;
+        }
+        return mFilteredChannels.get(channelIndex);
+    }
+
+    /**
+     * Returns the index of provided {@link Channel} within the currently managed channels.
+     * Returns -1 if such a channel is not found.
+     */
+    int getChannelIndex(Channel channel) {
+        return mFilteredChannels.indexOf(channel);
+    }
+
+    /**
+     * Returns the index of channel with  {@code channelId} within the currently managed channels.
+     * Returns -1 if such a channel is not found.
+     */
+    int getChannelIndex(long channelId) {
+        return getChannelIndex(mChannelDataManager.getChannel(channelId));
+    }
+
+    /**
+     * Returns the number of "entries", which lies within the currently managed time range, for a
+     * given {@code channelId}.
+     */
+    int getTableEntryCount(long channelId) {
+        return mChannelIdEntriesMap.get(channelId).size();
+    }
+
+    /**
+     * Returns an entry as {@link Program} for a given {@code channelId} and {@code index} of
+     * entries within the currently managed time range. Returned {@link Program} can be a dummy one
+     * (e.g., whose channelId is INVALID_ID), when it corresponds to a gap between programs.
+     */
+    TableEntry getTableEntry(long channelId, int index) {
+        return mChannelIdEntriesMap.get(channelId).get(index);
+    }
+
+    /**
      * Returns list genre ID's which has a channel.
      */
-    public List<Integer> getFilteredGenreIds() {
+    List<Integer> getFilteredGenreIds() {
         return mFilteredGenreIds;
     }
 
-    public int getSelectedGenreId() {
+    int getSelectedGenreId() {
         return mSelectedGenreId;
     }
 
@@ -439,11 +443,24 @@
         mChannels = mChannelDataManager.getBrowsableChannelList();
         mSelectedGenreId = GenreItems.ID_ALL_CHANNELS;
         mFilteredChannels = mChannels;
+        updateTableEntriesWithoutNotification(clearPreviousTableEntries);
+        // Channel update notification should be called after updating table entries, so that
+        // the listener can get the entries.
         notifyChannelsUpdated();
-        updateTableEntries(clearPreviousTableEntries);
+        notifyTableEntriesUpdated();
+        buildGenreFilters();
     }
 
     private void updateTableEntries(boolean clear) {
+        updateTableEntriesWithoutNotification(clear);
+        notifyTableEntriesUpdated();
+        buildGenreFilters();
+    }
+
+    /**
+     * Updates the table entries without notifying the change.
+     */
+    private void updateTableEntriesWithoutNotification(boolean clear) {
         if (clear) {
             mChannelIdEntriesMap.clear();
         }
@@ -491,46 +508,41 @@
                 }
             }
         }
-
-        notifyTableEntriesUpdated();
-        buildGenreFilters();
     }
 
-    private void notifyGenresUpdated() {
-        for (Listener listener : mListeners) {
-            listener.onGenresUpdated();
+    /**
+     * Build genre filters based on the current programs.
+     * This categories channels by its current program's canonical genres
+     * and subsequent @{link resetChannelListWithGenre(int)} calls will reset channel list
+     * with built channel list.
+     * This is expected to be called whenever program guide is shown.
+     */
+    private void buildGenreFilters() {
+        if (DEBUG) Log.d(TAG, "buildGenreFilters");
+
+        mGenreChannelList.clear();
+        for (int i = 0; i < GenreItems.getGenreCount(); i++) {
+            mGenreChannelList.add(new ArrayList<>());
         }
-    }
-
-    private void notifyChannelsUpdated() {
-        for (Listener listener : mListeners) {
-            listener.onChannelsUpdated();
+        for (Channel channel : mChannels) {
+            Program currentProgram = mProgramDataManager.getCurrentProgram(channel.getId());
+            if (currentProgram != null && currentProgram.getCanonicalGenres() != null) {
+                for (String genre : currentProgram.getCanonicalGenres()) {
+                    mGenreChannelList.get(GenreItems.getId(genre)).add(channel);
+                }
+            }
         }
-    }
-
-    private void notifyTimeRangeUpdated() {
-        for (Listener listener : mListeners) {
-            listener.onTimeRangeUpdated();
+        mGenreChannelList.set(GenreItems.ID_ALL_CHANNELS, mChannels);
+        mFilteredGenreIds.clear();
+        mFilteredGenreIds.add(0);
+        for (int i = 1; i < GenreItems.getGenreCount(); i++) {
+            if (mGenreChannelList.get(i).size() > 0) {
+                mFilteredGenreIds.add(i);
+            }
         }
-    }
-
-    private void notifyTableEntriesUpdated() {
-        for (TableEntriesUpdatedListener listener : mTableEntriesUpdatedListeners) {
-            listener.onTableEntriesUpdated();
-        }
-    }
-
-    private void notifyTableEntryUpdated(TableEntry entry) {
-        for (TableEntryChangedListener listener : mTableEntryChangedListeners) {
-            listener.onTableEntryChanged(entry);
-        }
-    }
-
-    private void updateEntry(TableEntry old, TableEntry newEntry) {
-        List<TableEntry> entries = mChannelIdEntriesMap.get(old.channelId);
-        int index = entries.indexOf(old);
-        entries.set(index, newEntry);
-        notifyTableEntryUpdated(newEntry);
+        mSelectedGenreId = GenreItems.ID_ALL_CHANNELS;
+        mFilteredChannels = mChannels;
+        notifyGenresUpdated();
     }
 
     @Nullable
@@ -551,32 +563,11 @@
         return null;
     }
 
-    /**
-     * Returns the start time of currently managed time range, in UTC millisecond.
-     */
-    public long getFromUtcMillis() {
-        return mFromUtcMillis;
-    }
-
-    /**
-     * Returns the end time of currently managed time range, in UTC millisecond.
-     */
-    public long getToUtcMillis() {
-        return mToUtcMillis;
-    }
-
-    /**
-     * Update the initial time range to manage. It updates program entries and genre as well.
-     */
-    public void updateInitialTimeRange(long startUtcMillis, long endUtcMillis) {
-        mStartUtcMillis = startUtcMillis;
-        if (endUtcMillis > mEndUtcMillis) {
-            mEndUtcMillis = endUtcMillis;
-        }
-
-        mProgramDataManager.setPrefetchTimeRange(mStartUtcMillis);
-        updateChannels(true);
-        setTimeRange(startUtcMillis, endUtcMillis);
+    private void updateEntry(TableEntry old, TableEntry newEntry) {
+        List<TableEntry> entries = mChannelIdEntriesMap.get(old.channelId);
+        int index = entries.indexOf(old);
+        entries.set(index, newEntry);
+        notifyTableEntryUpdated(newEntry);
     }
 
     private void setTimeRange(long fromUtcMillis, long toUtcMillis) {
@@ -592,57 +583,6 @@
         }
     }
 
-    /**
-     * Returns the number of the currently managed channels.
-     */
-    public int getChannelCount() {
-        return mFilteredChannels.size();
-    }
-
-    /**
-     * Returns a {@link Channel} at a given {@code channelIndex} of the currently managed channels.
-     * Returns {@code null} if such a channel is not found.
-     */
-    public Channel getChannel(int channelIndex) {
-        if (channelIndex < 0 || channelIndex >= getChannelCount()) {
-            return null;
-        }
-        return mFilteredChannels.get(channelIndex);
-    }
-
-    /**
-     * Returns the index of provided {@link Channel} within the currently managed channels.
-     * Returns -1 if such a channel is not found.
-     */
-    public int getChannelIndex(Channel channel) {
-        return mFilteredChannels.indexOf(channel);
-    }
-
-    /**
-     * Returns the index of channel with  {@code channelId} within the currently managed channels.
-     * Returns -1 if such a channel is not found.
-     */
-    public int getChannelIndex(long channelId) {
-        return getChannelIndex(mChannelDataManager.getChannel(channelId));
-    }
-
-    /**
-     * Returns the number of "entries", which lies within the currently managed time range, for a
-     * given {@code channelId}.
-     */
-    public int getTableEntryCount(long channelId) {
-        return mChannelIdEntriesMap.get(channelId).size();
-    }
-
-    /**
-     * Returns an entry as {@link Program} for a given {@code channelId} and {@code index} of
-     * entries within the currently managed time range. Returned {@link Program} can be a dummy one
-     * (e.g., whose channelId is INVALID_ID), when it corresponds to a gap between programs.
-     */
-    public TableEntry getTableEntry(long channelId, int index) {
-        return mChannelIdEntriesMap.get(channelId).get(index);
-    }
-
     private List<TableEntry> createProgramEntries(long channelId, boolean parentalControlsEnabled) {
         List<TableEntry> entries = new ArrayList<>();
         boolean channelLocked = parentalControlsEnabled
@@ -690,21 +630,152 @@
         return entries;
     }
 
-    public interface Listener {
+    private void notifyGenresUpdated() {
+        for (Listener listener : mListeners) {
+            listener.onGenresUpdated();
+        }
+    }
+
+    private void notifyChannelsUpdated() {
+        for (Listener listener : mListeners) {
+            listener.onChannelsUpdated();
+        }
+    }
+
+    private void notifyTimeRangeUpdated() {
+        for (Listener listener : mListeners) {
+            listener.onTimeRangeUpdated();
+        }
+    }
+
+    private void notifyTableEntriesUpdated() {
+        for (TableEntriesUpdatedListener listener : mTableEntriesUpdatedListeners) {
+            listener.onTableEntriesUpdated();
+        }
+    }
+
+    private void notifyTableEntryUpdated(TableEntry entry) {
+        for (TableEntryChangedListener listener : mTableEntryChangedListeners) {
+            listener.onTableEntryChanged(entry);
+        }
+    }
+
+    /**
+     * Entry for program guide table. An "entry" can be either an actual program or a gap between
+     * programs. This is needed for {@link ProgramListAdapter} because
+     * {@link android.support.v17.leanback.widget.HorizontalGridView} ignores margins between items.
+     */
+    static class TableEntry {
+        /** Channel ID which this entry is included. */
+        final long channelId;
+
+        /** Program corresponding to the entry. {@code null} means that this entry is a gap. */
+        final Program program;
+
+        final ScheduledRecording scheduledRecording;
+
+        /** Start time of entry in UTC milliseconds. */
+        final long entryStartUtcMillis;
+
+        /** End time of entry in UTC milliseconds */
+        final long entryEndUtcMillis;
+
+        private final boolean mIsBlocked;
+
+        private TableEntry(long channelId, long startUtcMillis, long endUtcMillis) {
+            this(channelId, null, startUtcMillis, endUtcMillis, false);
+        }
+
+        private TableEntry(long channelId, long startUtcMillis, long endUtcMillis,
+                           boolean blocked) {
+            this(channelId, null, null, startUtcMillis, endUtcMillis, blocked);
+        }
+
+        private TableEntry(long channelId, Program program, long entryStartUtcMillis,
+                           long entryEndUtcMillis, boolean isBlocked) {
+            this(channelId, program, null, entryStartUtcMillis, entryEndUtcMillis, isBlocked);
+        }
+
+        private TableEntry(long channelId, Program program, ScheduledRecording scheduledRecording,
+                           long entryStartUtcMillis, long entryEndUtcMillis, boolean isBlocked) {
+            this.channelId = channelId;
+            this.program = program;
+            this.scheduledRecording = scheduledRecording;
+            this.entryStartUtcMillis = entryStartUtcMillis;
+            this.entryEndUtcMillis = entryEndUtcMillis;
+            mIsBlocked = isBlocked;
+        }
+
+        /**
+         * A stable id useful for {@link android.support.v7.widget.RecyclerView.Adapter}.
+         */
+        long getId() {
+            // using a negative entryEndUtcMillis keeps it from conflicting with program Id
+            return program != null ? program.getId() : -entryEndUtcMillis;
+        }
+
+        /**
+         * Returns true if this is a gap.
+         */
+        boolean isGap() {
+            return !Program.isValid(program);
+        }
+
+        /**
+         * Returns true if this channel is blocked.
+         */
+        boolean isBlocked() {
+            return mIsBlocked;
+        }
+
+        /**
+         * Returns true if this program is on the air.
+         */
+        boolean isCurrentProgram() {
+            long current = System.currentTimeMillis();
+            return entryStartUtcMillis <= current && entryEndUtcMillis > current;
+        }
+
+        /**
+         * Returns if this program has the genre.
+         */
+        boolean hasGenre(int genreId) {
+            return !isGap() && program.hasGenre(genreId);
+        }
+
+        /**
+         * Returns the width of table entry, in pixels.
+         */
+        int getWidth() {
+            return GuideUtils.convertMillisToPixel(entryStartUtcMillis, entryEndUtcMillis);
+        }
+
+        @Override
+        public String toString() {
+            return "TableEntry{"
+                    + "hashCode=" + hashCode()
+                    + ", channelId=" + channelId
+                    + ", program=" + program
+                    + ", startTime=" + Utils.toTimeString(entryStartUtcMillis)
+                    + ", endTimeTime=" + Utils.toTimeString(entryEndUtcMillis) + "}";
+        }
+    }
+
+    interface Listener {
         void onGenresUpdated();
         void onChannelsUpdated();
         void onTimeRangeUpdated();
     }
 
-    public interface TableEntriesUpdatedListener {
+    interface TableEntriesUpdatedListener {
         void onTableEntriesUpdated();
     }
 
-    public interface TableEntryChangedListener {
+    interface TableEntryChangedListener {
         void onTableEntryChanged(TableEntry entry);
     }
 
-    public static class ListenerAdapter implements Listener {
+    static class ListenerAdapter implements Listener {
         @Override
         public void onGenresUpdated() { }
 
@@ -714,65 +785,4 @@
         @Override
         public void onTimeRangeUpdated() { }
     }
-
-    /**
-     * Shifts the time range by the given time. Also makes ProgramGuide scroll the views.
-     */
-    public void shiftTime(long timeMillisToScroll) {
-        long fromUtcMillis = mFromUtcMillis + timeMillisToScroll;
-        long toUtcMillis = mToUtcMillis + timeMillisToScroll;
-        if (fromUtcMillis < mStartUtcMillis) {
-            fromUtcMillis = mStartUtcMillis;
-            toUtcMillis += mStartUtcMillis - fromUtcMillis;
-        }
-        if (toUtcMillis > mEndUtcMillis) {
-            fromUtcMillis -= toUtcMillis - mEndUtcMillis;
-            toUtcMillis = mEndUtcMillis;
-        }
-        setTimeRange(fromUtcMillis, toUtcMillis);
-    }
-
-    /**
-     * Returned the scrolled(shifted) time in milliseconds.
-     */
-    public long getShiftedTime() {
-        return mFromUtcMillis - mStartUtcMillis;
-    }
-
-    /**
-     * Returns the start time set by {@link #updateInitialTimeRange}.
-     */
-    public long getStartTime() {
-        return mStartUtcMillis;
-    }
-
-    /**
-     * Returns the program index of the program with {@code entryId} or -1 if not found.
-     */
-    public int getProgramIdIndex(long channelId, long entryId) {
-        List<TableEntry> entries = mChannelIdEntriesMap.get(channelId);
-        if (entries != null) {
-            for (int i = 0; i < entries.size(); i++) {
-                if (entries.get(i).getId() == entryId) {
-                    return i;
-                }
-            }
-        }
-        return -1;
-    }
-
-    /**
-     * Returns the program index of the program at {@code time} or -1 if not found.
-     */
-    public int getProgramIndexAtTime(long channelId, long time) {
-        List<TableEntry> entries = mChannelIdEntriesMap.get(channelId);
-        for (int i = 0; i < entries.size(); ++i) {
-            TableEntry entry = entries.get(i);
-            if (entry.entryStartUtcMillis <= time
-                    && time < entry.entryEndUtcMillis) {
-                return i;
-            }
-        }
-        return -1;
-    }
 }
diff --git a/src/com/android/tv/guide/ProgramRow.java b/src/com/android/tv/guide/ProgramRow.java
index 2c98ab2..fefc724 100644
--- a/src/com/android/tv/guide/ProgramRow.java
+++ b/src/com/android/tv/guide/ProgramRow.java
@@ -21,9 +21,11 @@
 import android.support.v7.widget.LinearLayoutManager;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.util.Range;
 import android.view.View;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
 
+import com.android.tv.MainActivity;
 import com.android.tv.data.Channel;
 import com.android.tv.guide.ProgramManager.TableEntry;
 import com.android.tv.util.Utils;
@@ -37,6 +39,7 @@
     private static final long ONE_HOUR_MILLIS = TimeUnit.HOURS.toMillis(1);
     private static final long HALF_HOUR_MILLIS = ONE_HOUR_MILLIS / 2;
 
+    private ProgramGuide mProgramGuide;
     private ProgramManager mProgramManager;
 
     private boolean mKeepFocusToCurrentProgram;
@@ -44,8 +47,8 @@
 
     interface ChildFocusListener {
         /**
-         * Is called after focus is moved. It used {@link ChildFocusListener#isChild} to decide if
-         * old and new focuses are listener's children.
+         * Is called after focus is moved. Caller should check if old and new focuses are
+         * listener's children.
          * See {@code ProgramRow#setChildFocusListener(ChildFocusListener)}.
          */
         void onChildFocus(View oldFocus, View newFocus);
@@ -213,7 +216,6 @@
                 // so give focus back in onChildAttachedToWindow().
                 mKeepFocusToCurrentProgram = true;
             }
-            // TODO: Try to keep focus for non-current program.
         }
         super.onChildDetachedFromWindow(child);
     }
@@ -237,16 +239,18 @@
 
     @Override
     public boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
-        // Give focus to the current program by default.
-        // Note that this logic is used only if requestFocus() is called to the ProgramRow,
-        // so focus finding logic will not be blocked by this.
-        View currentProgram = getCurrentProgramView();
-        if (currentProgram != null) {
-            return currentProgram.requestFocus();
+        ProgramGrid programGrid = mProgramGuide.getProgramGrid();
+
+        // Give focus according to the previous focused range
+        Range<Integer> focusRange = programGrid.getFocusRange();
+        View nextFocus = GuideUtils.findNextFocusedProgram(this, focusRange.getLower(),
+                focusRange.getUpper(), programGrid.isKeepCurrentProgramFocused());
+
+        if (nextFocus != null) {
+            return nextFocus.requestFocus();
         }
 
         if (DEBUG) Log.d(TAG, "onRequestFocusInDescendants");
-
         boolean result = super.onRequestFocusInDescendants(direction, previouslyFocusedRect);
         if (!result) {
             // The default focus search logic of LeanbackLibrary is sometimes failed.
@@ -276,10 +280,11 @@
     }
 
     /**
-     * Sets the instance of {@link ProgramManager}
+     * Sets the instance of {@link ProgramGuide}
      */
-    public void setProgramManager(ProgramManager programManager) {
-        mProgramManager = programManager;
+    public void setProgramGuide(ProgramGuide programGuide) {
+        mProgramGuide = programGuide;
+        mProgramManager = programGuide.getProgramManager();
     }
 
     /**
@@ -300,7 +305,7 @@
                     .scrollToPositionWithOffset(position, offset);
             // Workaround to b/31598505. When a program's duration is too long,
             // RecyclerView.onScrolled() will not be called after scrollToPositionWithOffset().
-            // Therefore we have to update children's visible areas by ourselves in theis case.
+            // Therefore we have to update children's visible areas by ourselves in this case.
             // Since scrollToPositionWithOffset() will call requestLayout(), we can listen to this
             // behavior to ensure program items' visible areas are correctly updated after layouts
             // are adjusted, i.e., scrolling is over.
diff --git a/src/com/android/tv/guide/ProgramTableAdapter.java b/src/com/android/tv/guide/ProgramTableAdapter.java
index e4a6797..99f853b 100644
--- a/src/com/android/tv/guide/ProgramTableAdapter.java
+++ b/src/com/android/tv/guide/ProgramTableAdapter.java
@@ -45,19 +45,21 @@
 import android.view.ViewParent;
 import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
+import com.android.tv.common.TvCommonUtils;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.data.Channel;
 import com.android.tv.data.Program;
 import com.android.tv.data.Program.CriticScore;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.guide.ProgramManager.TableEntriesUpdatedListener;
 import com.android.tv.parental.ParentalControlSettings;
 import com.android.tv.ui.HardwareLayerAnimatorListenerAdapter;
@@ -73,7 +75,7 @@
 /**
  * Adapts the {@link ProgramListAdapter} list to the body of the program guide table.
  */
-public class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapter.ProgramRowHolder>
+class ProgramTableAdapter extends RecyclerView.Adapter<ProgramTableAdapter.ProgramRowViewHolder>
         implements ProgramManager.TableEntryChangedListener {
     private static final String TAG = "ProgramTableAdapter";
     private static final boolean DEBUG = false;
@@ -112,8 +114,7 @@
     private final int mDvrPaddingStartWithTrack;
     private final int mDvrPaddingStartWithOutTrack;
 
-    public ProgramTableAdapter(Context context, ProgramManager programManager,
-            ProgramGuide programGuide) {
+    ProgramTableAdapter(Context context, ProgramGuide programGuide) {
         mContext = context;
         mAccessibilityManager =
                 (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
@@ -125,8 +126,8 @@
             mDvrManager = null;
             mDvrDataManager = null;
         }
-        mProgramManager = programManager;
         mProgramGuide = programGuide;
+        mProgramManager = programGuide.getProgramManager();
 
         Resources res = context.getResources();
         mChannelLogoWidth = res.getDimensionPixelSize(
@@ -193,7 +194,7 @@
         mProgramListAdapters.clear();
         for (int i = 0; i < mProgramManager.getChannelCount(); i++) {
             ProgramListAdapter listAdapter = new ProgramListAdapter(mContext.getResources(),
-                    mProgramManager, i);
+                    mProgramGuide, i);
             mProgramManager.addTableEntriesUpdatedListener(listAdapter);
             mProgramListAdapters.add(listAdapter);
         }
@@ -211,12 +212,12 @@
     }
 
     @Override
-    public void onBindViewHolder(ProgramRowHolder holder, int position) {
+    public void onBindViewHolder(ProgramRowViewHolder holder, int position) {
         holder.onBind(position);
     }
 
     @Override
-    public void onBindViewHolder(ProgramRowHolder holder, int position, List<Object> payloads) {
+    public void onBindViewHolder(ProgramRowViewHolder holder, int position, List<Object> payloads) {
         if (!payloads.isEmpty()) {
             holder.updateDetailView();
         } else {
@@ -225,11 +226,11 @@
     }
 
     @Override
-    public ProgramRowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+    public ProgramRowViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
         View itemView = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
         ProgramRow programRow = (ProgramRow) itemView.findViewById(R.id.row);
         programRow.setRecycledViewPool(mRecycledViewPool);
-        return new ProgramRowHolder(itemView);
+        return new ProgramRowViewHolder(itemView);
     }
 
     @Override
@@ -241,18 +242,7 @@
         notifyItemChanged(channelIndex, true);
     }
 
-    @Override
-    public void onViewAttachedToWindow(ProgramRowHolder holder) {
-        holder.onAttachedToWindow();
-    }
-
-    @Override
-    public void onViewDetachedFromWindow(ProgramRowHolder holder) {
-        holder.onDetachedFromWindow();
-    }
-
-    // TODO: make it static
-    public class ProgramRowHolder extends RecyclerView.ViewHolder
+    class ProgramRowViewHolder extends RecyclerView.ViewHolder
             implements ProgramRow.ChildFocusListener {
 
         private final ViewGroup mContainer;
@@ -269,6 +259,12 @@
                 }
             }
         };
+        private final Runnable mUpdateDetailViewRunnable = new Runnable() {
+            @Override
+            public void run() {
+                updateDetailView();
+            }
+        };
 
         private final RecyclerView.OnScrollListener mOnScrollListener =
                 new RecyclerView.OnScrollListener() {
@@ -282,8 +278,9 @@
                 new ViewTreeObserver.OnGlobalFocusChangeListener() {
                     @Override
                     public void onGlobalFocusChanged(View oldFocus, View newFocus) {
-                        onChildFocus(isChild(oldFocus) ? oldFocus : null,
-                                isChild(newFocus) ? newFocus : null);
+                        onChildFocus(
+                                GuideUtils.isDescendant(mContainer, oldFocus) ? oldFocus : null,
+                                GuideUtils.isDescendant(mContainer, newFocus) ? newFocus : null);
                     }
                 };
 
@@ -312,11 +309,38 @@
         private final ImageView mInputLogoView;
 
         private boolean mIsInputLogoVisible;
+        private AccessibilityStateChangeListener mAccessibilityStateChangeListener =
+                new AccessibilityManager.AccessibilityStateChangeListener() {
+                    @Override
+                    public void onAccessibilityStateChanged(boolean enable) {
+                        enable &= !TvCommonUtils.isRunningInTest();
+                        mDetailView.setFocusable(enable);
+                        mChannelHeaderView.setFocusable(enable);
+                    }
+                };
 
-        public ProgramRowHolder(View itemView) {
+        ProgramRowViewHolder(View itemView) {
             super(itemView);
 
             mContainer = (ViewGroup) itemView;
+            mContainer.addOnAttachStateChangeListener(
+                    new View.OnAttachStateChangeListener() {
+                        @Override
+                        public void onViewAttachedToWindow(View v) {
+                            mContainer.getViewTreeObserver()
+                                    .addOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
+                            mAccessibilityManager.addAccessibilityStateChangeListener(
+                                    mAccessibilityStateChangeListener);
+                        }
+
+                        @Override
+                        public void onViewDetachedFromWindow(View v) {
+                            mContainer.getViewTreeObserver()
+                                    .removeOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
+                            mAccessibilityManager.removeAccessibilityStateChangeListener(
+                                    mAccessibilityStateChangeListener);
+                        }
+                    });
             mProgramRow = (ProgramRow) mContainer.findViewById(R.id.row);
 
             mDetailView = (ViewGroup) mContainer.findViewById(R.id.detail);
@@ -339,23 +363,18 @@
             mChannelLogoView = (ImageView) mContainer.findViewById(R.id.channel_logo);
             mChannelBlockView = (ImageView) mContainer.findViewById(R.id.channel_block);
             mInputLogoView = (ImageView) mContainer.findViewById(R.id.input_logo);
-            mDetailView.setFocusable(mAccessibilityManager.isEnabled());
-            mChannelHeaderView.setFocusable(mAccessibilityManager.isEnabled());
-            mAccessibilityManager.addAccessibilityStateChangeListener(
-                    new AccessibilityManager.AccessibilityStateChangeListener() {
-                        @Override
-                        public void onAccessibilityStateChanged(boolean enable) {
-                            mDetailView.setFocusable(enable);
-                            mChannelHeaderView.setFocusable(enable);
-                        }
-                    });
+
+            boolean accessibilityEnabled = mAccessibilityManager.isEnabled()
+                    && !TvCommonUtils.isRunningInTest();
+            mDetailView.setFocusable(accessibilityEnabled);
+            mChannelHeaderView.setFocusable(accessibilityEnabled);
         }
 
         public void onBind(int position) {
             onBindChannel(mProgramManager.getChannel(position));
 
             mProgramRow.swapAdapter(mProgramListAdapters.get(position), true);
-            mProgramRow.setProgramManager(mProgramManager);
+            mProgramRow.setProgramGuide(mProgramGuide);
             mProgramRow.setChannel(mProgramManager.getChannel(position));
             mProgramRow.setChildFocusListener(this);
             mProgramRow.resetScroll(mProgramGuide.getTimelineRowScrollOffset());
@@ -416,24 +435,11 @@
             }
         }
 
-        public boolean isChild(View view) {
-            if (view == null) {
-                return false;
-            }
-            for (ViewParent p = view.getParent(); p != null; p = p.getParent()) {
-                if (p == mContainer) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
         @Override
         public void onChildFocus(View oldFocus, View newFocus) {
             if (newFocus == null) {
                 return;
-            }
-            // When the accessibility service is enabled, focus might be put on channel's header or
+            }            // When the accessibility service is enabled, focus might be put on channel's header or
             // detail view, besides program items.
             if (newFocus == mChannelHeaderView) {
                 mSelectedEntry = ((ProgramItemView) mProgramRow.getChildAt(0)).getTableEntry();
@@ -443,7 +449,15 @@
                 mSelectedEntry = ((ProgramItemView) newFocus).getTableEntry();
             }
             if (oldFocus == null) {
-                updateDetailView();
+                // Focus moved from other row.
+                if (mProgramGuide.getProgramGrid().isInLayout()) {
+                    // We need to post runnable to avoid updating detail view when
+                    // the recycler view is in layout, which may cause detail view not
+                    // laid out according to the updated contents.
+                    mHandler.post(mUpdateDetailViewRunnable);
+                } else {
+                    updateDetailView();
+                }
                 return;
             }
 
@@ -508,16 +522,6 @@
                     });
         }
 
-        private void onAttachedToWindow() {
-            mContainer.getViewTreeObserver()
-                    .addOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
-        }
-
-        private void onDetachedFromWindow() {
-            mContainer.getViewTreeObserver()
-                    .removeOnGlobalFocusChangeListener(mGlobalFocusChangeListener);
-        }
-
         private void updateDetailView() {
             if (mSelectedEntry == null) {
                 // The view holder is never on focus before.
@@ -556,10 +560,8 @@
                         program.getStartTimeUtcMillis(),
                         program.getEndTimeUtcMillis(), false));
 
-                boolean trackMetaDataVisible = false;
-                trackMetaDataVisible |=
-                        updateTextView(mAspectRatioView, Utils.getAspectRatioString(
-                        program.getVideoWidth(), program.getVideoHeight()));
+                boolean trackMetaDataVisible = updateTextView(mAspectRatioView, Utils
+                        .getAspectRatioString(program.getVideoWidth(), program.getVideoHeight()));
 
                 int videoDefinitionLevel = Utils.getVideoDefinitionLevelFromSize(
                         program.getVideoWidth(), program.getVideoHeight());
@@ -658,7 +660,9 @@
             if (TextUtils.isEmpty(name)) {
                 return mContext.getString(R.string.program_guide_content_locked);
             } else {
-                return mContext.getString(R.string.program_guide_content_locked_format, name);
+                return TvContentRating.UNRATED.equals(blockedRating)
+                        ? mContext.getString(R.string.program_guide_content_locked_unrated)
+                        : mContext.getString(R.string.program_guide_content_locked_format, name);
             }
         }
 
@@ -666,7 +670,7 @@
          * Update tv input logo. It should be called when the visible child item in ProgramGrid
          * changed.
          */
-        public void updateInputLogo(int lastPosition, boolean forceShow) {
+        void updateInputLogo(int lastPosition, boolean forceShow) {
             if (mChannel == null) {
                 mInputLogoView.setVisibility(View.GONE);
                 mIsInputLogoVisible = false;
@@ -731,7 +735,7 @@
             mInputLogoView.setVisibility(View.VISIBLE);
         }
 
-        private void updateCriticScoreView(ProgramRowHolder holder, final long programId,
+        private void updateCriticScoreView(ProgramRowViewHolder holder, final long programId,
                 CriticScore criticScore, View view) {
             TextView criticScoreSource = (TextView) view.findViewById(R.id.critic_score_source);
             TextView criticScoreText = (TextView) view.findViewById(R.id.critic_score_score);
@@ -759,11 +763,11 @@
         }
     }
 
-    private static ImageLoaderCallback<ProgramRowHolder> createCriticScoreLogoCallback(
-            ProgramRowHolder holder, final long programId, ImageView logoView) {
-        return new ImageLoaderCallback<ProgramRowHolder>(holder) {
+    private static ImageLoaderCallback<ProgramRowViewHolder> createCriticScoreLogoCallback(
+            ProgramRowViewHolder holder, final long programId, ImageView logoView) {
+        return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
             @Override
-            public void onBitmapLoaded(ProgramRowHolder holder, @Nullable Bitmap logoImage) {
+            public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logoImage) {
                 if (logoImage == null || holder.mSelectedEntry == null
                         || holder.mSelectedEntry.program == null
                         || holder.mSelectedEntry.program.getId() != programId) {
@@ -776,11 +780,11 @@
         };
     }
 
-    private static ImageLoaderCallback<ProgramRowHolder> createProgramPosterArtCallback(
-            ProgramRowHolder holder, final Program program) {
-        return new ImageLoaderCallback<ProgramRowHolder>(holder) {
+    private static ImageLoaderCallback<ProgramRowViewHolder> createProgramPosterArtCallback(
+            ProgramRowViewHolder holder, final Program program) {
+        return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
             @Override
-            public void onBitmapLoaded(ProgramRowHolder holder, @Nullable Bitmap posterArt) {
+            public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap posterArt) {
                 if (posterArt == null || holder.mSelectedEntry == null
                         || holder.mSelectedEntry.program == null) {
                     return;
@@ -794,11 +798,11 @@
         };
     }
 
-    private static ImageLoaderCallback<ProgramRowHolder> createChannelLogoLoadedCallback(
-            ProgramRowHolder holder, final long channelId) {
-        return new ImageLoaderCallback<ProgramRowHolder>(holder) {
+    private static ImageLoaderCallback<ProgramRowViewHolder> createChannelLogoLoadedCallback(
+            ProgramRowViewHolder holder, final long channelId) {
+        return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
             @Override
-            public void onBitmapLoaded(ProgramRowHolder holder, @Nullable Bitmap logo) {
+            public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logo) {
                 if (logo == null || holder.mChannel == null
                         || holder.mChannel.getId() != channelId) {
                     return;
@@ -808,11 +812,11 @@
         };
     }
 
-    private static ImageLoaderCallback<ProgramRowHolder> createTvInputLogoLoadedCallback(
-            final TvInputInfo info, ProgramRowHolder holder) {
-        return new ImageLoaderCallback<ProgramRowHolder>(holder) {
+    private static ImageLoaderCallback<ProgramRowViewHolder> createTvInputLogoLoadedCallback(
+            final TvInputInfo info, ProgramRowViewHolder holder) {
+        return new ImageLoaderCallback<ProgramRowViewHolder>(holder) {
             @Override
-            public void onBitmapLoaded(ProgramRowHolder holder, @Nullable Bitmap logo) {
+            public void onBitmapLoaded(ProgramRowViewHolder holder, @Nullable Bitmap logo) {
                 if (logo != null && holder.mChannel != null && info.getId()
                         .equals(holder.mChannel.getInputId())) {
                     holder.updateInputLogoInternal(logo);
diff --git a/src/com/android/tv/guide/TimeListAdapter.java b/src/com/android/tv/guide/TimeListAdapter.java
index 868fed4..d9e96a4 100644
--- a/src/com/android/tv/guide/TimeListAdapter.java
+++ b/src/com/android/tv/guide/TimeListAdapter.java
@@ -16,6 +16,7 @@
 
 package com.android.tv.guide;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.support.v7.widget.RecyclerView;
 import android.text.format.DateFormat;
@@ -25,26 +26,40 @@
 import android.widget.TextView;
 
 import com.android.tv.R;
+import com.android.tv.util.Utils;
 
 import java.util.Date;
+import java.util.Locale;
 import java.util.concurrent.TimeUnit;
 
 /**
  * Adapts the time range from {@link ProgramManager} to the timeline header row of the program
  * guide table.
  */
-public class TimeListAdapter extends RecyclerView.Adapter<TimeListAdapter.TimeViewHolder> {
+class TimeListAdapter extends RecyclerView.Adapter<TimeListAdapter.TimeViewHolder> {
     private static final long TIME_UNIT_MS = TimeUnit.MINUTES.toMillis(30);
+
+    // Ex. 3:00 AM
+    private static final String TIME_PATTERN_SAME_DAY = "h:mm a";
+    // Ex. Oct 21, 3:00 AM
+    private static final String TIME_PATTERN_DIFFERENT_DAY = "MMM d, h:mm a";
+
     private static int sRowHeaderOverlapping;
 
     // Nearest half hour at or before the start time.
     private long mStartUtcMs;
+    private final String mTimePatternSameDay;
+    private final String mTimePatternDifferentDay;
 
-    public TimeListAdapter(Resources res) {
+    TimeListAdapter(Resources res) {
         if (sRowHeaderOverlapping == 0) {
             sRowHeaderOverlapping = Math.abs(res.getDimensionPixelOffset(
                     R.dimen.program_guide_table_header_row_overlap));
         }
+        Locale locale = res.getConfiguration().locale;
+        mTimePatternSameDay = DateFormat.getBestDateTimePattern(locale, TIME_PATTERN_SAME_DAY);
+        mTimePatternDifferentDay =
+                DateFormat.getBestDateTimePattern(locale, TIME_PATTERN_DIFFERENT_DAY);
     }
 
     public void update(long startTimeMs) {
@@ -68,10 +83,14 @@
         long endTime = startTime + TIME_UNIT_MS;
 
         View itemView = holder.itemView;
-
-        TextView textView = (TextView) itemView.findViewById(R.id.time);
-        String time = DateFormat.getTimeFormat(itemView.getContext()).format(new Date(startTime));
-        textView.setText(time);
+        Date timeDate = new Date(startTime);
+        String timeString;
+        if (Utils.isInGivenDay(System.currentTimeMillis(), startTime)) {
+            timeString = DateFormat.format(mTimePatternSameDay, timeDate).toString();
+        } else {
+            timeString = DateFormat.format(mTimePatternDifferentDay, timeDate).toString();
+        }
+        ((TextView) itemView.findViewById(R.id.time)).setText(timeString);
 
         RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) itemView.getLayoutParams();
         lp.width = GuideUtils.convertMillisToPixel(startTime, endTime);
@@ -90,8 +109,8 @@
         return new TimeViewHolder(itemView);
     }
 
-    public static class TimeViewHolder extends RecyclerView.ViewHolder {
-        public TimeViewHolder(View itemView) {
+    static class TimeViewHolder extends RecyclerView.ViewHolder {
+        TimeViewHolder(View itemView) {
             super(itemView);
         }
     }
diff --git a/src/com/android/tv/license/License.java b/src/com/android/tv/license/License.java
new file mode 100644
index 0000000..c1cbd09
--- /dev/null
+++ b/src/com/android/tv/license/License.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 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.license;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Container class to store the name of a library and the filename of its associated license file.
+ */
+public final class License implements Comparable<License>, Parcelable {
+    // Name of the third-party library.
+    private final String mLibraryName;
+    // Byte offset in the file to the start of the license text.
+    private final long mLicenseOffset;
+    // Byte length of the license text.
+    private final int mLicenseLength;
+    // Path to the archive that has bundled licenses.
+    // Empty string if the license is bundled in the apk itself.
+    private final String mPath;
+
+    /**
+     * Create an object representing a stored license. The text for all licenses is stored in a
+     * single file, so the offset and length describe this license's position within the file.
+     *
+     * @param path a path to an .apk-compatible archive that contains the license. An empty string
+     *     in case the license is contained within the app itself.
+     */
+    static License create(String libraryName, long licenseOffset, int licenseLength, String path) {
+        return new License(libraryName, licenseOffset, licenseLength, path);
+    }
+
+    public static final Parcelable.Creator<License> CREATOR =
+            new Parcelable.Creator<License>() {
+                @Override
+                public License createFromParcel(Parcel in) {
+                    return new License(in);
+                }
+
+                @Override
+                public License[] newArray(int size) {
+                    return new License[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mLibraryName);
+        dest.writeLong(mLicenseOffset);
+        dest.writeInt(mLicenseLength);
+        dest.writeString(mPath);
+    }
+
+    @Override
+    public int compareTo(License o) {
+        return mLibraryName.compareToIgnoreCase(o.getLibraryName());
+    }
+
+    @Override
+    public String toString() {
+        return getLibraryName();
+    }
+
+    private License(String libraryName, long licenseOffset, int licenseLength, String path) {
+        this.mLibraryName = libraryName;
+        this.mLicenseOffset = licenseOffset;
+        this.mLicenseLength = licenseLength;
+        this.mPath = path;
+    }
+
+    private License(Parcel in) {
+        mLibraryName = in.readString();
+        mLicenseOffset = in.readLong();
+        mLicenseLength = in.readInt();
+        mPath = in.readString();
+    }
+
+    String getLibraryName() {
+        return mLibraryName;
+    }
+
+    long getLicenseOffset() {
+        return mLicenseOffset;
+    }
+
+    int getLicenseLength() {
+        return mLicenseLength;
+    }
+
+    public String getPath() {
+        return mPath;
+    }
+}
diff --git a/src/com/android/tv/license/LicenseDialogFragment.java b/src/com/android/tv/license/LicenseDialogFragment.java
new file mode 100644
index 0000000..b0e0977
--- /dev/null
+++ b/src/com/android/tv/license/LicenseDialogFragment.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 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.license;
+
+import android.app.DialogFragment;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.text.method.ScrollingMovementMethod;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.TextView;
+
+import com.android.tv.R;
+import com.android.tv.dialog.SafeDismissDialogFragment;
+
+/** A DialogFragment that shows a License in a text view. */
+public class LicenseDialogFragment extends SafeDismissDialogFragment {
+    public static final String DIALOG_TAG = LicenseDialogFragment.class.getSimpleName();
+
+    private static final String LICENSE = "LICENSE";
+
+    private License mLicense;
+    private String mTrackerLabel;
+
+    /**
+     * Create a new LicenseDialogFragment to show a particular license.
+     *
+     * @param license The License to show.
+     */
+    public static LicenseDialogFragment newInstance(License license) {
+        LicenseDialogFragment f = new LicenseDialogFragment();
+        Bundle args = new Bundle();
+        args.putParcelable(LICENSE, license);
+        f.setArguments(args);
+        return f;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mLicense = getArguments().getParcelable(LICENSE);
+        String title = mLicense.getLibraryName();
+        mTrackerLabel = getArguments().getString(title + "_license");
+        int style =
+                TextUtils.isEmpty(title)
+                        ? DialogFragment.STYLE_NO_TITLE
+                        : DialogFragment.STYLE_NORMAL;
+        setStyle(style, 0);
+    }
+
+    @Nullable
+    @Override
+    public View onCreateView(
+            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        TextView textView = new TextView(getActivity());
+        String licenseText = Licenses.getLicenseText(getContext(), mLicense);
+        textView.setText(licenseText != null ? licenseText : "");
+        textView.setMovementMethod(new ScrollingMovementMethod());
+        int verticalOverscan =
+                getResources().getDimensionPixelSize(R.dimen.vertical_overscan_safe_margin);
+        int horizontalOverscan =
+                getResources().getDimensionPixelSize(R.dimen.horizontal_overscan_safe_margin);
+        textView.setPadding(
+                horizontalOverscan, verticalOverscan, horizontalOverscan, verticalOverscan);
+        return textView;
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        // Ensure the dialog is fullscreen, even if the TextView doesn't have its content yet.
+        getDialog().getWindow().setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+        getDialog().setTitle(mLicense.getLibraryName());
+    }
+
+    @Override
+    public String getTrackerLabel() {
+        return mTrackerLabel;
+    }
+}
diff --git a/src/com/android/tv/license/LicenseSideFragment.java b/src/com/android/tv/license/LicenseSideFragment.java
new file mode 100644
index 0000000..fd92467
--- /dev/null
+++ b/src/com/android/tv/license/LicenseSideFragment.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 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.license;
+
+import android.content.Context;
+
+import com.android.tv.R;
+import com.android.tv.ui.sidepanel.ActionItem;
+import com.android.tv.ui.sidepanel.SideFragment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Opens a dialog showing open source licenses. */
+public final class LicenseSideFragment extends SideFragment {
+
+    public static final String TRACKER_LABEL = "Open Source Licenses";
+
+    public class LicenseActionItem extends ActionItem {
+        private final License license;
+
+        public LicenseActionItem(License license) {
+            super(license.getLibraryName());
+            this.license = license;
+        }
+
+        @Override
+        protected void onSelected() {
+            LicenseDialogFragment dialog = LicenseDialogFragment.newInstance(license);
+            getMainActivity()
+                    .getOverlayManager()
+                    .showDialogFragment(LicenseDialogFragment.DIALOG_TAG, dialog, true);
+        }
+    }
+
+    private List<LicenseActionItem> licenses;
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        licenses = toActionItems(Licenses.getLicenses(context));
+    }
+
+    private List<LicenseActionItem> toActionItems(ArrayList<License> licenses) {
+        List<LicenseActionItem> items = new ArrayList<>(licenses.size());
+        for (License license : licenses) {
+            items.add(new LicenseActionItem(license));
+        }
+        return items;
+    }
+
+    @Override
+    protected String getTitle() {
+        return getResources().getString(R.string.settings_menu_licenses);
+    }
+
+    @Override
+    public String getTrackerLabel() {
+        return TRACKER_LABEL;
+    }
+
+    @Override
+    protected List<LicenseActionItem> getItemList() {
+        return licenses;
+    }
+}
diff --git a/src/com/android/tv/license/LicenseUtils.java b/src/com/android/tv/license/LicenseUtils.java
index b972aad..cf3fe75 100644
--- a/src/com/android/tv/license/LicenseUtils.java
+++ b/src/com/android/tv/license/LicenseUtils.java
@@ -26,21 +26,9 @@
  * Utilities for showing open source licenses.
  */
 public final class LicenseUtils {
-    public final static String LICENSE_FILE = "file:///android_asset/licenses.html";
     public final static String RATING_SOURCE_FILE =
             "file:///android_asset/rating_sources.html";
-    private final static File licenseFile = new File(LICENSE_FILE);
 
-    /**
-     * Checks if the license.html asset is include in the apk.
-     */
-    public static boolean hasLicenses(AssetManager am) {
-        try (InputStream is = am.open("licenses.html")) {
-            return true;
-        } catch (IOException e) {
-            return false;
-        }
-    }
 
     /**
      * Checks if the rating_attribution.html asset is include in the apk.
diff --git a/src/com/android/tv/license/Licenses.java b/src/com/android/tv/license/Licenses.java
new file mode 100644
index 0000000..4b8a7ff
--- /dev/null
+++ b/src/com/android/tv/license/Licenses.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2017 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.license;
+
+import android.content.Context;
+import android.support.annotation.RawRes;
+
+import com.android.tv.R;
+import com.android.tv.common.SoftPreconditions;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collections;
+
+/**
+ * A helper for extracting licenses embedded using
+ * third_party_licenses.build:third_party_licenses().
+ */
+public final class Licenses {
+
+    public static final String TAG = "Licenses";
+    public static boolean hasLicenses(Context context) {
+        return !getTextFromResource(
+                        context.getApplicationContext(), R.raw.third_party_license_metadata, 0, -1)
+                .isEmpty();
+    }
+
+    /** Return the licenses bundled into this app. */
+    public static ArrayList<License> getLicenses(Context context) {
+        return getLicenseListFromMetadata(
+                getTextFromResource(
+                        context.getApplicationContext(), R.raw.third_party_license_metadata, 0, -1),
+                "");
+    }
+
+    /**
+     * Returns a list of {@link License}s parsed from a license metadata file.
+     *
+     * @param metadata a {@code String} containing the contents of a license metadata file.
+     * @param filePath a path to a package archive with licenses or empty string for the app package
+     */
+    private static ArrayList<License> getLicenseListFromMetadata(String metadata, String filePath) {
+        String[] entries = metadata.split("\n");
+        ArrayList<License> licenses = new ArrayList<License>(entries.length);
+        for (String entry : entries) {
+            int delimiter = entry.indexOf(' ');
+            String[] licenseLocation = entry.substring(0, delimiter).split(":");
+            SoftPreconditions.checkState(
+                    licenseLocation.length == 2 && delimiter > 0,
+                    TAG,
+                    "Invalid license meta-data line:\n" + entry);
+            long licenseOffset = Long.parseLong(licenseLocation[0]);
+            int licenseLength = Integer.parseInt(licenseLocation[1]);
+            licenses.add(
+                    License.create(
+                            entry.substring(delimiter + 1),
+                            licenseOffset,
+                            licenseLength,
+                            filePath));
+        }
+        Collections.sort(licenses);
+        return licenses;
+    }
+
+    /** Return the text of a bundled license file. */
+    public static String getLicenseText(Context context, License license) {
+        long offset = license.getLicenseOffset();
+        int length = license.getLicenseLength();
+        return getTextFromResource(context, R.raw.third_party_licenses, offset, length);
+    }
+
+    private static String getTextFromResource(
+            Context context, @RawRes int resourcesIdentifier, long offset, int length) {
+        InputStream stream =
+                context.getApplicationContext().getResources().openRawResource(resourcesIdentifier);
+        return getTextFromInputStream(stream, offset, length);
+    }
+
+    private static String getTextFromInputStream(InputStream stream, long offset, int length) {
+        byte[] buffer = new byte[1024];
+        ByteArrayOutputStream textArray = new ByteArrayOutputStream();
+
+        try {
+            stream.skip(offset);
+            int bytesRemaining = length > 0 ? length : Integer.MAX_VALUE;
+            int bytes = 0;
+
+            while (bytesRemaining > 0
+                    && (bytes = stream.read(buffer, 0, Math.min(bytesRemaining, buffer.length)))
+                            != -1) {
+                textArray.write(buffer, 0, bytes);
+                bytesRemaining -= bytes;
+            }
+            stream.close();
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to read license or metadata text.", e);
+        }
+        try {
+            return textArray.toString("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(
+                    "Unsupported encoding UTF8. This should always be supported.", e);
+        }
+    }
+}
diff --git a/src/com/android/tv/menu/ActionCardView.java b/src/com/android/tv/menu/ActionCardView.java
index 54892ca..2fd70bf 100644
--- a/src/com/android/tv/menu/ActionCardView.java
+++ b/src/com/android/tv/menu/ActionCardView.java
@@ -19,8 +19,8 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
-import android.widget.FrameLayout;
 import android.widget.ImageView;
+import android.widget.RelativeLayout;
 import android.widget.TextView;
 
 import com.android.tv.R;
@@ -28,7 +28,7 @@
 /**
  * A view to render an item of TV options.
  */
-public class ActionCardView extends FrameLayout implements ItemListRowView.CardView<MenuAction> {
+public class ActionCardView extends RelativeLayout implements ItemListRowView.CardView<MenuAction> {
     private static final String TAG = MenuView.TAG;
     private static final boolean DEBUG = MenuView.DEBUG;
 
@@ -66,7 +66,7 @@
         }
         mIconView.setImageDrawable(action.getDrawable(getContext()));
         mLabelView.setText(action.getActionName(getContext()));
-        mStateView.setText(action.getActionDescription(getContext()));
+        mStateView.setText(action.getActionDescription());
         if (action.isEnabled()) {
             setEnabled(true);
             setFocusable(true);
diff --git a/src/com/android/tv/menu/AppLinkCardView.java b/src/com/android/tv/menu/AppLinkCardView.java
index bfb5e3f..94ccd37 100644
--- a/src/com/android/tv/menu/AppLinkCardView.java
+++ b/src/com/android/tv/menu/AppLinkCardView.java
@@ -24,6 +24,7 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.AsyncTask;
 import android.support.annotation.Nullable;
 import android.support.v7.graphics.Palette;
 import android.text.TextUtils;
@@ -40,10 +41,12 @@
 import com.android.tv.util.ImageLoader;
 import com.android.tv.util.TvInputManagerHelper;
 
+import java.util.Objects;
+
 /**
  * A view to render an app link card.
  */
-public class AppLinkCardView extends BaseCardView<Channel> {
+public class AppLinkCardView extends BaseCardView<ChannelsRowItem> {
     private static final String TAG = MenuView.TAG;
     private static final boolean DEBUG = MenuView.DEBUG;
 
@@ -53,9 +56,9 @@
     private final int mIconHeight;
     private final int mIconPadding;
     private final int mIconColorFilter;
+    private final Drawable mDefaultDrawable;
 
     private ImageView mImageView;
-    private View mGradientView;
     private TextView mAppInfoView;
     private View mMetaViewHolder;
     private Channel mChannel;
@@ -82,6 +85,7 @@
         mPackageManager = context.getPackageManager();
         mTvInputManagerHelper = ((MainActivity) context).getTvInputManagerHelper();
         mIconColorFilter = getResources().getColor(R.color.app_link_card_icon_color_filter, null);
+        mDefaultDrawable = getResources().getDrawable(R.drawable.ic_recent_thumbnail_default, null);
     }
 
     /**
@@ -92,65 +96,153 @@
     }
 
     @Override
-    public void onBind(Channel channel, boolean selected) {
+    public void onBind(ChannelsRowItem item, boolean selected) {
+        Channel newChannel = item.getChannel();
+        boolean channelChanged = !Objects.equals(mChannel, newChannel);
+        String previousPosterArtUri = mChannel == null ? null : mChannel.getAppLinkPosterArtUri();
+        boolean posterArtChanged = previousPosterArtUri == null
+                || newChannel.getAppLinkPosterArtUri() == null
+                || !TextUtils.equals(previousPosterArtUri, newChannel.getAppLinkPosterArtUri());
+        mChannel = newChannel;
         if (DEBUG) {
-            Log.d(TAG, "onBind(channelName=" + channel.getDisplayName() + ", selected=" + selected
+            Log.d(TAG, "onBind(channelName=" + mChannel.getDisplayName() + ", selected=" + selected
                     + ")");
         }
-        mChannel = channel;
         ApplicationInfo appInfo = mTvInputManagerHelper.getTvInputAppInfo(mChannel.getInputId());
-        int linkType = mChannel.getAppLinkType(getContext());
-        mIntent = mChannel.getAppLinkIntent(getContext());
+        if (channelChanged) {
+            int linkType = mChannel.getAppLinkType(getContext());
+            mIntent = mChannel.getAppLinkIntent(getContext());
 
-        switch (linkType) {
-            case Channel.APP_LINK_TYPE_CHANNEL:
-                setText(mChannel.getAppLinkText());
-                mAppInfoView.setVisibility(VISIBLE);
-                mGradientView.setVisibility(VISIBLE);
-                mAppInfoView.setCompoundDrawablePadding(mIconPadding);
-                mAppInfoView.setCompoundDrawables(null, null, null, null);
-                mAppInfoView.setText(mPackageManager.getApplicationLabel(appInfo));
-                if (!TextUtils.isEmpty(mChannel.getAppLinkIconUri())) {
-                    mChannel.loadBitmap(getContext(), Channel.LOAD_IMAGE_TYPE_APP_LINK_ICON,
-                            mIconWidth, mIconHeight, createChannelLogoCallback(this, mChannel,
-                                    Channel.LOAD_IMAGE_TYPE_APP_LINK_ICON));
-                } else if (appInfo.icon != 0) {
-                    Drawable appIcon = mPackageManager.getApplicationIcon(appInfo);
-                    BitmapUtils.setColorFilterToDrawable(mIconColorFilter, appIcon);
-                    appIcon.setBounds(0, 0, mIconWidth, mIconHeight);
-                    mAppInfoView.setCompoundDrawables(appIcon, null, null, null);
-                }
-                break;
-            case Channel.APP_LINK_TYPE_APP:
-                setText(getContext().getString(
-                        R.string.channels_item_app_link_app_launcher,
-                        mPackageManager.getApplicationLabel(appInfo)));
-                mAppInfoView.setVisibility(GONE);
-                mGradientView.setVisibility(GONE);
-                break;
-            default:
-                mAppInfoView.setVisibility(GONE);
-                mGradientView.setVisibility(GONE);
-                Log.d(TAG, "Should not be here.");
-        }
+            CharSequence appLabel;
+            switch (linkType) {
+                case Channel.APP_LINK_TYPE_CHANNEL:
+                    setText(mChannel.getAppLinkText());
+                    mAppInfoView.setVisibility(VISIBLE);
+                    mAppInfoView.setCompoundDrawablePadding(mIconPadding);
+                    mAppInfoView.setCompoundDrawablesRelative(null, null, null, null);
+                    appLabel = mTvInputManagerHelper
+                            .getTvInputApplicationLabel(mChannel.getInputId());
+                    if (appLabel != null) {
+                        mAppInfoView.setText(appLabel);
+                    } else {
+                        new AsyncTask<Void, Void, CharSequence>() {
+                            private final String mLoadTvInputId = mChannel.getInputId();
 
-        if (mChannel.getAppLinkColor() == 0) {
-            mMetaViewHolder.setBackgroundResource(R.color.channel_card_meta_background);
-        } else {
-            mMetaViewHolder.setBackgroundColor(mChannel.getAppLinkColor());
-        }
+                            @Override
+                            protected CharSequence doInBackground(Void... params) {
+                                if (appInfo != null) {
+                                    return mPackageManager.getApplicationLabel(appInfo);
+                                }
+                                return null;
+                            }
 
-        if (!TextUtils.isEmpty(mChannel.getAppLinkPosterArtUri())) {
-            mImageView.setImageResource(R.drawable.ic_recent_thumbnail_default);
-            mChannel.loadBitmap(getContext(), Channel.LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART,
-                    mCardImageWidth, mCardImageHeight, createChannelLogoCallback(this, mChannel,
-                            Channel.LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART));
-        } else {
-            setCardImageWithBanner(appInfo);
+                            @Override
+                            protected void onPostExecute(CharSequence appLabel) {
+                                mTvInputManagerHelper.setTvInputApplicationLabel(
+                                        mLoadTvInputId, appLabel);
+                                if (mLoadTvInputId != mChannel.getInputId()
+                                        || !isAttachedToWindow()) {
+                                    return;
+                                }
+                                mAppInfoView.setText(appLabel);
+                            }
+                        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+                    }
+                    if (!TextUtils.isEmpty(mChannel.getAppLinkIconUri())) {
+                        mChannel.loadBitmap(getContext(), Channel.LOAD_IMAGE_TYPE_APP_LINK_ICON,
+                                mIconWidth, mIconHeight, createChannelLogoCallback(
+                                        this, mChannel, Channel.LOAD_IMAGE_TYPE_APP_LINK_ICON));
+                    } else if (appInfo.icon != 0) {
+                        Drawable appIcon = mTvInputManagerHelper
+                                .getTvInputApplicationIcon(mChannel.getInputId());
+                        if (appIcon != null) {
+                            BitmapUtils.setColorFilterToDrawable(mIconColorFilter, appIcon);
+                            appIcon.setBounds(0, 0, mIconWidth, mIconHeight);
+                            mAppInfoView.setCompoundDrawablesRelative(appIcon, null, null, null);
+                        } else {
+                            new AsyncTask<Void, Void, Drawable>() {
+                                private final String mLoadTvInputId = mChannel.getInputId();
+
+                                @Override
+                                protected Drawable doInBackground(Void... params) {
+                                    return mPackageManager.getApplicationIcon(appInfo);
+                                }
+
+                                @Override
+                                protected void onPostExecute(Drawable appIcon) {
+                                    mTvInputManagerHelper.setTvInputApplicationIcon(
+                                            mLoadTvInputId, appIcon);
+                                    if (!mLoadTvInputId.equals(mChannel.getInputId())
+                                            || !isAttachedToWindow()) {
+                                        return;
+                                    }
+                                    BitmapUtils.setColorFilterToDrawable(mIconColorFilter, appIcon);
+                                    appIcon.setBounds(0, 0, mIconWidth, mIconHeight);
+                                    mAppInfoView.setCompoundDrawablesRelative(
+                                            appIcon, null, null, null);
+                                }
+                            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+                        }
+                    }
+                    break;
+                case Channel.APP_LINK_TYPE_APP:
+                    appLabel = mTvInputManagerHelper
+                        .getTvInputApplicationLabel(mChannel.getInputId());
+                    if (appLabel != null) {
+                        setText(getContext()
+                            .getString(R.string.channels_item_app_link_app_launcher, appLabel));
+                    } else {
+                        new AsyncTask<Void, Void, CharSequence>() {
+                            private final String mLoadTvInputId = mChannel.getInputId();
+
+                            @Override
+                            protected CharSequence doInBackground(Void... params) {
+                                if (appInfo != null) {
+                                    return mPackageManager.getApplicationLabel(appInfo);
+                                }
+                                return null;
+                            }
+
+                            @Override
+                            protected void onPostExecute(CharSequence appLabel) {
+                                mTvInputManagerHelper.setTvInputApplicationLabel(
+                                    mLoadTvInputId, appLabel);
+                                if (!mLoadTvInputId.equals(mChannel.getInputId())
+                                    || !isAttachedToWindow()) {
+                                    return;
+                                }
+                                setText(getContext()
+                                    .getString(
+                                        R.string.channels_item_app_link_app_launcher,
+                                        appLabel));
+                            }
+                        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+                    }
+                    mAppInfoView.setVisibility(GONE);
+                    break;
+                default:
+                    mAppInfoView.setVisibility(GONE);
+                    Log.d(TAG, "Should not be here.");
+            }
+
+            if (mChannel.getAppLinkColor() == 0) {
+                mMetaViewHolder.setBackgroundResource(R.color.channel_card_meta_background);
+            } else {
+                mMetaViewHolder.setBackgroundColor(mChannel.getAppLinkColor());
+            }
         }
-        // Call super.onBind() at the end intentionally. In order to correctly handle extension of
-        // text view, text should be set before calling super.onBind.
-        super.onBind(channel, selected);
+        if (posterArtChanged) {
+            mImageView.setImageDrawable(mDefaultDrawable);
+            mImageView.setForeground(null);
+            if (!TextUtils.isEmpty(mChannel.getAppLinkPosterArtUri())) {
+                mChannel.loadBitmap(getContext(), Channel.LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART,
+                        mCardImageWidth, mCardImageHeight, createChannelLogoCallback(this, mChannel,
+                                Channel.LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART));
+            } else {
+                setCardImageWithBanner(appInfo);
+            }
+        }
+        super.onBind(item, selected);
     }
 
     private static ImageLoader.ImageLoaderCallback<AppLinkCardView> createChannelLogoCallback(
@@ -182,13 +274,14 @@
                 }
             }
             BitmapUtils.setColorFilterToDrawable(mIconColorFilter, drawable);
-            mAppInfoView.setCompoundDrawables(drawable, null, null, null);
+            mAppInfoView.setCompoundDrawablesRelative(drawable, null, null, null);
         } else if (type == Channel.LOAD_IMAGE_TYPE_APP_LINK_POSTER_ART) {
             if (bitmap == null) {
                 setCardImageWithBanner(
                         mTvInputManagerHelper.getTvInputAppInfo(mChannel.getInputId()));
             } else {
                 mImageView.setImageBitmap(bitmap);
+                mImageView.setForeground(getContext().getDrawable(R.drawable.card_image_gradient));
                 if (mChannel.getAppLinkColor() == 0) {
                     extractAndSetMetaViewBackgroundColor(bitmap);
                 }
@@ -200,7 +293,6 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mImageView = (ImageView) findViewById(R.id.image);
-        mGradientView = findViewById(R.id.image_gradient);
         mAppInfoView = (TextView) findViewById(R.id.app_info);
         mMetaViewHolder = findViewById(R.id.app_link_text_holder);
     }
@@ -209,37 +301,85 @@
     // 1) Provided poster art image, 2) Activity banner, 3) Activity icon, 4) Application banner,
     // 5) Application icon, and 6) default image.
     private void setCardImageWithBanner(ApplicationInfo appInfo) {
-        Drawable banner = null;
-        if (mIntent != null) {
-            try {
-                banner = mPackageManager.getActivityBanner(mIntent);
-                if (banner == null) {
-                    banner = mPackageManager.getActivityIcon(mIntent);
+        new AsyncTask<Void, Void, Drawable>() {
+            private String mLoadTvInputId = mChannel.getInputId();
+            @Override
+            protected Drawable doInBackground(Void... params) {
+                Drawable banner = null;
+                if (mIntent != null) {
+                    try {
+                        banner = mPackageManager.getActivityBanner(mIntent);
+                        if (banner == null) {
+                            banner = mPackageManager.getActivityIcon(mIntent);
+                        }
+                    } catch (PackageManager.NameNotFoundException e) {
+                        // do nothing.
+                    }
                 }
-            } catch (PackageManager.NameNotFoundException e) {
-                // do nothing.
+                return banner;
             }
-        }
 
-        if (banner == null && appInfo != null) {
-            if (appInfo.banner != 0) {
-                banner = mPackageManager.getApplicationBanner(appInfo);
+            @Override
+            protected void onPostExecute(Drawable banner) {
+                if (mLoadTvInputId != mChannel.getInputId() || !isAttachedToWindow()) {
+                    return;
+                }
+                if (banner != null) {
+                    setCardImageWithBannerInternal(banner);
+                } else {
+                    setCardImageWithApplicationInfoBanner(appInfo);
+                }
             }
-            if (banner == null && appInfo.icon != 0) {
-                banner = mPackageManager.getApplicationIcon(appInfo);
-            }
-        }
+        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+    }
 
+    private void setCardImageWithApplicationInfoBanner(ApplicationInfo appInfo) {
+        Drawable appBanner =
+                mTvInputManagerHelper.getTvInputApplicationBanner(mChannel.getInputId());
+        if (appBanner != null) {
+            setCardImageWithBannerInternal(appBanner);
+        } else {
+            new AsyncTask<Void, Void, Drawable>() {
+                private final String mLoadTvInputId = mChannel.getInputId();
+                @Override
+                protected Drawable doInBackground(Void... params) {
+                    Drawable banner = null;
+                    if (appInfo != null) {
+                        if (appInfo.banner != 0) {
+                            banner = mPackageManager.getApplicationBanner(appInfo);
+                        }
+                        if (banner == null && appInfo.icon != 0) {
+                            banner = mPackageManager.getApplicationIcon(appInfo);
+                        }
+                    }
+                    return banner;
+                }
+
+                @Override
+                protected void onPostExecute(Drawable banner) {
+                    mTvInputManagerHelper.setTvInputApplicationBanner(mLoadTvInputId, banner);
+                    if (!TextUtils.equals(mLoadTvInputId, mChannel.getInputId())
+                            || !isAttachedToWindow()) {
+                        return;
+                    }
+                    setCardImageWithBannerInternal(banner);
+                }
+            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
+        }
+    }
+
+    private void setCardImageWithBannerInternal(Drawable banner) {
         if (banner == null) {
-            mImageView.setImageResource(R.drawable.ic_recent_thumbnail_default);
+            mImageView.setImageDrawable(mDefaultDrawable);
             mImageView.setBackgroundResource(R.color.channel_card);
         } else {
-            Bitmap bitmap =
-                    Bitmap.createBitmap(mCardImageWidth, mCardImageHeight, Bitmap.Config.ARGB_8888);
+            Bitmap bitmap = Bitmap.createBitmap(
+                    mCardImageWidth, mCardImageHeight, Bitmap.Config.ARGB_8888);
             Canvas canvas = new Canvas(bitmap);
             banner.setBounds(0, 0, mCardImageWidth, mCardImageHeight);
             banner.draw(canvas);
             mImageView.setImageDrawable(banner);
+            mImageView.setForeground(getContext().getDrawable(R.drawable.card_image_gradient));
             if (mChannel.getAppLinkColor() == 0) {
                 extractAndSetMetaViewBackgroundColor(bitmap);
             }
diff --git a/src/com/android/tv/menu/BaseCardView.java b/src/com/android/tv/menu/BaseCardView.java
index c6a34a5..4c5e6c7 100644
--- a/src/com/android/tv/menu/BaseCardView.java
+++ b/src/com/android/tv/menu/BaseCardView.java
@@ -22,6 +22,7 @@
 import android.content.Context;
 import android.graphics.Outline;
 import android.support.annotation.Nullable;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.ViewGroup;
@@ -35,9 +36,6 @@
  * A base class to render a card.
  */
 public abstract class BaseCardView<T> extends LinearLayout implements ItemListRowView.CardView<T> {
-    private static final String TAG = "BaseCardView";
-    private static final boolean DEBUG = false;
-
     private static final float SCALE_FACTOR_0F = 0f;
     private static final float SCALE_FACTOR_1F = 1f;
 
@@ -57,6 +55,11 @@
     private TextView mTextViewFocused;
     private final int mCardImageWidth;
     private final float mCardHeight;
+    private boolean mSelected;
+
+    private int mTextResId;
+    private String mTextString;
+    private boolean mTextChanged;
 
     public BaseCardView(Context context) {
         this(context, null);
@@ -103,23 +106,9 @@
 
     /**
      * Called when the view is displayed.
-     *
-     * Before onBind is called, this view's text should be set to determine if it'll be extended
-     * or not in focus state.
      */
     @Override
     public void onBind(T item, boolean selected) {
-        if (mTextView != null && mTextViewFocused != null) {
-            mTextViewFocused.measure(
-                    MeasureSpec.makeMeasureSpec(mCardImageWidth, MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-            mExtendViewOnFocus = mTextViewFocused.getLineCount() > 1;
-            if (mExtendViewOnFocus) {
-                setTextViewFocusedAlpha(selected ? 1f : 0f);
-            } else {
-                setTextViewFocusedAlpha(1f);
-            }
-        }
         setFocusAnimatedValue(selected ? SCALE_FACTOR_1F : SCALE_FACTOR_0F);
     }
 
@@ -128,6 +117,7 @@
 
     @Override
     public void onSelected() {
+        mSelected = true;
         if (isAttachedToWindow() && getVisibility() == View.VISIBLE) {
             startFocusAnimation(SCALE_FACTOR_1F);
         } else {
@@ -138,6 +128,7 @@
 
     @Override
     public void onDeselected() {
+        mSelected = false;
         if (isAttachedToWindow() && getVisibility() == View.VISIBLE) {
             startFocusAnimation(SCALE_FACTOR_0F);
         } else {
@@ -150,11 +141,17 @@
      * Sets text of this card view.
      */
     public void setText(int resId) {
-        if (mTextViewFocused != null) {
-            mTextViewFocused.setText(resId);
-        }
-        if (mTextView != null) {
-            mTextView.setText(resId);
+        if (mTextResId != resId) {
+            mTextResId = resId;
+            mTextString = null;
+            mTextChanged = true;
+            if (mTextViewFocused != null) {
+                mTextViewFocused.setText(resId);
+            }
+            if (mTextView != null) {
+                mTextView.setText(resId);
+            }
+            onTextViewUpdated();
         }
     }
 
@@ -162,12 +159,33 @@
      * Sets text of this card view.
      */
     public void setText(String text) {
-        if (mTextViewFocused != null) {
-            mTextViewFocused.setText(text);
+        if (!TextUtils.equals(text, mTextString)) {
+            mTextString = text;
+            mTextResId = 0;
+            mTextChanged = true;
+            if (mTextViewFocused != null) {
+                mTextViewFocused.setText(text);
+            }
+            if (mTextView != null) {
+                mTextView.setText(text);
+            }
+            onTextViewUpdated();
         }
-        if (mTextView != null) {
-            mTextView.setText(text);
+    }
+
+    private void onTextViewUpdated() {
+        if (mTextView != null && mTextViewFocused != null) {
+            mTextViewFocused.measure(
+                MeasureSpec.makeMeasureSpec(mCardImageWidth, MeasureSpec.EXACTLY),
+                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+            mExtendViewOnFocus = mTextViewFocused.getLineCount() > 1;
+            if (mExtendViewOnFocus) {
+                setTextViewFocusedAlpha(mSelected ? 1f : 0f);
+            } else {
+                setTextViewFocusedAlpha(1f);
+            }
         }
+        setFocusAnimatedValue(mSelected ? SCALE_FACTOR_1F : SCALE_FACTOR_0F);
     }
 
     /**
@@ -209,12 +227,18 @@
         setScaleX(scale);
         setScaleY(scale);
         setTranslationZ(mFocusTranslationZ * animatedValue);
-        if (mExtendViewOnFocus) {
+        if (mTextView != null && mTextViewFocused != null) {
             ViewGroup.LayoutParams params = mTextView.getLayoutParams();
-            params.height = Math.round(mTextViewHeight
-                    + (mExtendedTextViewHeight - mTextViewHeight) * animatedValue);
-            setTextViewLayoutParams(params);
-            setTextViewFocusedAlpha(animatedValue);
+            int height = mExtendViewOnFocus ? Math.round(mTextViewHeight
+                + (mExtendedTextViewHeight - mTextViewHeight) * animatedValue)
+                : (int) mTextViewHeight;
+            if (height != params.height) {
+                params.height = height;
+                setTextViewLayoutParams(params);
+            }
+            if (mExtendViewOnFocus) {
+                setTextViewFocusedAlpha(animatedValue);
+            }
         }
     }
 
diff --git a/src/com/android/tv/menu/ChannelCardView.java b/src/com/android/tv/menu/ChannelCardView.java
index 1c8015a..2ecb6af 100644
--- a/src/com/android/tv/menu/ChannelCardView.java
+++ b/src/com/android/tv/menu/ChannelCardView.java
@@ -34,10 +34,12 @@
 import com.android.tv.parental.ParentalControlSettings;
 import com.android.tv.util.ImageLoader;
 
+import java.util.Objects;
+
 /**
  * A view to render channel card.
  */
-public class ChannelCardView extends BaseCardView<Channel> {
+public class ChannelCardView extends BaseCardView<ChannelsRowItem> {
     private static final String TAG = MenuView.TAG;
     private static final boolean DEBUG = MenuView.DEBUG;
 
@@ -45,11 +47,11 @@
     private final int mCardImageHeight;
 
     private ImageView mImageView;
-    private View mGradientView;
     private TextView mChannelNumberNameView;
     private ProgressBar mProgressBar;
     private Channel mChannel;
     private Program mProgram;
+    private String mPosterArtUri;
     private final MainActivity mMainActivity;
 
     public ChannelCardView(Context context) {
@@ -71,39 +73,72 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mImageView = (ImageView) findViewById(R.id.image);
-        mGradientView = findViewById(R.id.image_gradient);
+        mImageView.setBackgroundResource(R.color.channel_card);
         mChannelNumberNameView = (TextView) findViewById(R.id.channel_number_and_name);
         mProgressBar = (ProgressBar) findViewById(R.id.progress);
     }
 
     @Override
-    public void onBind(Channel channel, boolean selected) {
+    public void onBind(ChannelsRowItem item, boolean selected) {
         if (DEBUG) {
-            Log.d(TAG, "onBind(channelName=" + channel.getDisplayName() + ", selected=" + selected
-                    + ")");
+            Log.d(TAG, "onBind(channelName=" + item.getChannel().getDisplayName() + ", selected="
+                    + selected + ")");
         }
-        mChannel = channel;
-        mProgram = null;
-        mChannelNumberNameView.setText(mChannel.getDisplayText());
-        mChannelNumberNameView.setVisibility(VISIBLE);
-        mImageView.setImageResource(R.drawable.ic_recent_thumbnail_default);
-        mImageView.setBackgroundResource(R.color.channel_card);
-        mGradientView.setVisibility(View.GONE);
-        mProgressBar.setVisibility(GONE);
+        updateChannel(item);
+        updateProgram();
+        super.onBind(item, selected);
+    }
 
-        setTextViewEnabled(true);
-        if (mMainActivity.getParentalControlSettings().isParentalControlsEnabled()
-                && mChannel.isLocked()) {
+    private void updateChannel(ChannelsRowItem item) {
+        if (!item.getChannel().equals(mChannel)) {
+            mChannel = item.getChannel();
+            mChannelNumberNameView.setText(mChannel.getDisplayText());
+            mChannelNumberNameView.setVisibility(VISIBLE);
+        }
+    }
+
+    private void updateProgram() {
+        ParentalControlSettings parental = mMainActivity.getParentalControlSettings();
+        if (parental.isParentalControlsEnabled() && mChannel.isLocked()) {
             setText(R.string.program_title_for_blocked_channel);
-            return;
+            mProgram = null;
         } else {
-            setText("");
+            Program currentProgram =
+                    mMainActivity.getProgramDataManager().getCurrentProgram(mChannel.getId());
+            if (!Objects.equals(currentProgram, mProgram)) {
+                mProgram = currentProgram;
+                if (mProgram == null || TextUtils.isEmpty(mProgram.getTitle())) {
+                    setTextViewEnabled(false);
+                    setText(R.string.program_title_for_no_information);
+                } else {
+                    setTextViewEnabled(true);
+                    setText(mProgram.getTitle());
+                }
+            }
         }
-
-        updateProgramInformation();
-        // Call super.onBind() at the end intentionally. In order to correctly handle extension of
-        // text view, text should be set before calling super.onBind.
-        super.onBind(channel, selected);
+        if (mProgram == null) {
+            mProgressBar.setVisibility(GONE);
+            setPosterArt(null);
+        } else {
+            // Update progress.
+            mProgressBar.setVisibility(View.VISIBLE);
+            long startTime = mProgram.getStartTimeUtcMillis();
+            long endTime = mProgram.getEndTimeUtcMillis();
+            long currTime = System.currentTimeMillis();
+            if (currTime <= startTime) {
+                mProgressBar.setProgress(0);
+            } else if (currTime >= endTime) {
+                mProgressBar.setProgress(100);
+            } else {
+                mProgressBar.setProgress(
+                        (int) (100 * (currTime - startTime) / (endTime - startTime)));
+            }
+            // Update image.
+            if (!parental.isParentalControlsEnabled()
+                    || !parental.isRatingBlocked(mProgram.getContentRatings())) {
+                setPosterArt(mProgram.getPosterArtUri());
+            }
+        }
     }
 
     private static ImageLoader.ImageLoaderCallback<ChannelCardView> createProgramPosterArtCallback(
@@ -121,49 +156,20 @@
         };
     }
 
+    private void setPosterArt(String posterArtUri) {
+        if (!TextUtils.equals(mPosterArtUri, posterArtUri)) {
+            mPosterArtUri = posterArtUri;
+            if (posterArtUri == null
+                    || !mProgram.loadPosterArt(getContext(), mCardImageWidth, mCardImageHeight,
+                            createProgramPosterArtCallback(this, mProgram))) {
+                mImageView.setImageResource(R.drawable.ic_recent_thumbnail_default);
+                mImageView.setForeground(null);
+            }
+        }
+    }
+
     private void updatePosterArt(Bitmap posterArt) {
         mImageView.setImageBitmap(posterArt);
-        mGradientView.setVisibility(View.VISIBLE);
+        mImageView.setForeground(getContext().getDrawable(R.drawable.card_image_gradient));
     }
-
-    private void updateProgramInformation() {
-        if (mChannel == null) {
-            return;
-        }
-        mProgram = mMainActivity.getProgramDataManager().getCurrentProgram(mChannel.getId());
-        if (mProgram == null || TextUtils.isEmpty(mProgram.getTitle())) {
-            setTextViewEnabled(false);
-            setText(R.string.program_title_for_no_information);
-        } else {
-            setText(mProgram.getTitle());
-        }
-
-        if (mProgram == null) {
-            return;
-        }
-
-        long startTime = mProgram.getStartTimeUtcMillis();
-        long endTime = mProgram.getEndTimeUtcMillis();
-        long currTime = System.currentTimeMillis();
-        mProgressBar.setVisibility(View.VISIBLE);
-        if (currTime <= startTime) {
-            mProgressBar.setProgress(0);
-        } else if (currTime >= endTime) {
-            mProgressBar.setProgress(100);
-        } else {
-            mProgressBar.setProgress((int) (100 * (currTime - startTime) / (endTime - startTime)));
-        }
-
-        if (!(getContext() instanceof MainActivity)) {
-            Log.e(TAG, "Fails to check program's content rating.");
-            return;
-        }
-        ParentalControlSettings parental = mMainActivity.getParentalControlSettings();
-        if ((!parental.isParentalControlsEnabled()
-                || !parental.isRatingBlocked(mProgram.getContentRatings()))
-                && !TextUtils.isEmpty(mProgram.getPosterArtUri())) {
-            mProgram.loadPosterArt(getContext(), mCardImageWidth, mCardImageHeight,
-                    createProgramPosterArtCallback(this, mProgram));
-        }
-    }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/menu/ChannelsPosterPrefetcher.java b/src/com/android/tv/menu/ChannelsPosterPrefetcher.java
index f932d75..bc5d6cf 100644
--- a/src/com/android/tv/menu/ChannelsPosterPrefetcher.java
+++ b/src/com/android/tv/menu/ChannelsPosterPrefetcher.java
@@ -97,12 +97,13 @@
 
         // This executes on the main thread, but since the item list is expected to be about 5 items
         // and ImageLoader spawns an async task so this is fast enough. 1 ms in local testing.
-        List<Channel> channelList = mChannelsAdapter.getItemList();
-        if (channelList != null) {
-            for (Channel channel : channelList) {
+        List<ChannelsRowItem> items = mChannelsAdapter.getItemList();
+        if (items != null) {
+            for (ChannelsRowItem item : items) {
                 if (isCanceled) {
                     return;
                 }
+                Channel channel = item.getChannel();
                 if (!Channel.isValid(channel)) {
                     continue;
                 }
@@ -116,7 +117,7 @@
         }
         if (DEBUG) {
             Log.d(TAG, "doPrefetchImages() finished. ImageLoader may still have async tasks for "
-                            + "channels " + channelList);
+                            + "channels " + items);
         }
     }
 
diff --git a/src/com/android/tv/menu/ChannelsRow.java b/src/com/android/tv/menu/ChannelsRow.java
index dedf099..490d73d 100644
--- a/src/com/android/tv/menu/ChannelsRow.java
+++ b/src/com/android/tv/menu/ChannelsRow.java
@@ -26,8 +26,14 @@
 public class ChannelsRow extends ItemListRow {
     public static final String ID = ChannelsRow.class.getName();
 
-    private static final int MIN_COUNT_FOR_RECENT_CHANNELS = 5;
-    private static final int MAX_COUNT_FOR_RECENT_CHANNELS = 10;
+    /**
+     * Minimum count for recent channels.
+     */
+    public static final int MIN_COUNT_FOR_RECENT_CHANNELS = 5;
+    /**
+     * Maximum count for recent channels.
+     */
+    public static final int MAX_COUNT_FOR_RECENT_CHANNELS = 10;
 
     private Recommender mTvRecommendation;
     private ChannelsRowAdapter mChannelsAdapter;
diff --git a/src/com/android/tv/menu/ChannelsRowAdapter.java b/src/com/android/tv/menu/ChannelsRowAdapter.java
index c8e1bd0..7ff44ea 100644
--- a/src/com/android/tv/menu/ChannelsRowAdapter.java
+++ b/src/com/android/tv/menu/ChannelsRowAdapter.java
@@ -31,17 +31,15 @@
 import com.android.tv.recommendation.Recommender;
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
-import com.android.tv.util.Utils;
 
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * An adapter of the Channels row.
  */
-public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<Channel> {
-    private static final String TAG = "ChannelsRowAdapter";
-
+public class ChannelsRowAdapter extends ItemListRowView.ItemListAdapter<ChannelsRowItem> {
     // There are four special cards: guide, setup, dvr, applink.
     private static final int SIZE_OF_VIEW_TYPE = 5;
 
@@ -51,7 +49,6 @@
     private final DvrDataManager mDvrDataManager;
     private final int mMaxCount;
     private final int mMinCount;
-    private final int[] mViewType = new int[SIZE_OF_VIEW_TYPE];
 
     private final View.OnClickListener mGuideOnClickListener = new View.OnClickListener() {
         @Override
@@ -113,14 +110,12 @@
         mRecommender = recommender;
         mMinCount = minCount;
         mMaxCount = maxCount;
+        setHasStableIds(true);
     }
 
     @Override
     public int getItemViewType(int position) {
-        if (position >= SIZE_OF_VIEW_TYPE) {
-            return R.layout.menu_card_channel;
-        }
-        return mViewType[position];
+        return getItemList().get(position).getLayoutId();
     }
 
     @Override
@@ -129,9 +124,12 @@
     }
 
     @Override
-    public void onBindViewHolder(MyViewHolder viewHolder, int position) {
-        super.onBindViewHolder(viewHolder, position);
+    public long getItemId(int position) {
+        return getItemList().get(position).getItemId();
+    }
 
+    @Override
+    public void onBindViewHolder(MyViewHolder viewHolder, int position) {
         int viewType = getItemViewType(position);
         if (viewType == R.layout.menu_card_guide) {
             viewHolder.itemView.setOnClickListener(mGuideOnClickListener);
@@ -144,80 +142,158 @@
             SimpleCardView view = (SimpleCardView) viewHolder.itemView;
             view.setText(R.string.channels_item_dvr);
         } else {
-            viewHolder.itemView.setTag(getItemList().get(position));
+            viewHolder.itemView.setTag(getItemList().get(position).getChannel());
             viewHolder.itemView.setOnClickListener(mChannelOnClickListener);
         }
+        super.onBindViewHolder(viewHolder, position);
     }
 
     @Override
     public void update() {
-        List<Channel> channelList = new ArrayList<>();
-        Channel dummyChannel = new Channel.Builder().build();
-        // For guide item
-        channelList.add(dummyChannel);
-        // For setup item
-        TvInputManagerHelper inputManager = TvApplication.getSingletons(mContext)
-                .getTvInputManagerHelper();
-        boolean showSetupCard = SetupUtils.getInstance(mContext).hasNewInput(inputManager);
-        Channel currentChannel = getMainActivity().getCurrentChannel();
-        boolean showAppLinkCard = currentChannel != null
-                && currentChannel.getAppLinkType(mContext) != Channel.APP_LINK_TYPE_NONE
-                // Sometimes applicationInfo can be null. b/28932537
-                && inputManager.getTvInputAppInfo(currentChannel.getInputId()) != null;
-        boolean showDvrCard = false;
+        if (getItemCount() == 0) {
+            createItems();
+        } else {
+            updateItems();
+        }
+    }
+
+    private void createItems() {
+        List<ChannelsRowItem> items = new ArrayList<>();
+        items.add(ChannelsRowItem.GUIDE_ITEM);
+        if (needToShowSetupItem()) {
+            items.add(ChannelsRowItem.SETUP_ITEM);
+        }
+        if (needToShowDvrItem()) {
+            items.add(ChannelsRowItem.DVR_ITEM);
+        }
+        if (needToShowAppLinkItem()) {
+            ChannelsRowItem.APP_LINK_ITEM.setChannel(
+                    new Channel.Builder(getMainActivity().getCurrentChannel()).build());
+            items.add(ChannelsRowItem.APP_LINK_ITEM);
+        }
+        for (Channel channel : getRecentChannels()) {
+            items.add(new ChannelsRowItem(channel, R.layout.menu_card_channel));
+        }
+        setItemList(items);
+    }
+
+    private void updateItems() {
+        List<ChannelsRowItem> items = getItemList();
+        // The current index of the item list to iterate. It starts from 1 because the first item
+        // (GUIDE) is always visible and not updated.
+        int currentIndex = 1;
+        if (updateItem(needToShowSetupItem(), ChannelsRowItem.SETUP_ITEM, currentIndex)) {
+            ++currentIndex;
+        }
+        if (updateItem(needToShowDvrItem(), ChannelsRowItem.DVR_ITEM, currentIndex)) {
+            ++currentIndex;
+        }
+        if (updateItem(needToShowAppLinkItem(), ChannelsRowItem.APP_LINK_ITEM, currentIndex)) {
+            if (!getMainActivity().getCurrentChannel()
+                    .hasSameReadOnlyInfo(ChannelsRowItem.APP_LINK_ITEM.getChannel())) {
+                ChannelsRowItem.APP_LINK_ITEM.setChannel(
+                        new Channel.Builder(getMainActivity().getCurrentChannel()).build());
+                notifyItemChanged(currentIndex);
+            }
+            ++currentIndex;
+        }
+        int numOldChannels = items.size() - currentIndex;
+        if (numOldChannels > 0) {
+            while (items.size() > currentIndex) {
+                items.remove(items.size() - 1);
+            }
+            notifyItemRangeRemoved(currentIndex, numOldChannels);
+        }
+        for (Channel channel : getRecentChannels()) {
+            items.add(new ChannelsRowItem(channel, R.layout.menu_card_channel));
+        }
+        int numNewChannels = items.size() - currentIndex;
+        if (numNewChannels > 0) {
+            notifyItemRangeInserted(currentIndex, numNewChannels);
+        }
+    }
+
+    /**
+     * Returns {@code true} if the item should be shown.
+     */
+    private boolean updateItem(boolean needToShow, ChannelsRowItem item, int index) {
+        List<ChannelsRowItem> items = getItemList();
+        boolean isItemInList = index < items.size() && item.equals(items.get(index));
+        if (needToShow && !isItemInList) {
+            items.add(index, item);
+            notifyItemInserted(index);
+        } else if (!needToShow && isItemInList) {
+            items.remove(index);
+            notifyItemRemoved(index);
+        }
+        return needToShow;
+    }
+
+    private boolean needToShowSetupItem() {
+        TvInputManagerHelper inputManager =
+                TvApplication.getSingletons(mContext).getTvInputManagerHelper();
+        return SetupUtils.getInstance(mContext).hasNewInput(inputManager);
+    }
+
+    private boolean needToShowDvrItem() {
+        TvInputManagerHelper inputManager =
+                TvApplication.getSingletons(mContext).getTvInputManagerHelper();
         if (mDvrDataManager != null) {
             for (TvInputInfo info : inputManager.getTvInputInfos(true, true)) {
                 if (info.canRecord()) {
-                    showDvrCard = true;
-                    break;
+                    return true;
                 }
             }
         }
+        return false;
+    }
 
-        mViewType[0] = R.layout.menu_card_guide;
-        int index = 1;
-        if (showSetupCard) {
-            channelList.add(dummyChannel);
-            mViewType[index++] = R.layout.menu_card_setup;
-        }
-        if (showDvrCard) {
-            channelList.add(dummyChannel);
-            mViewType[index++] = R.layout.menu_card_dvr;
-        }
-        if (showAppLinkCard) {
-            channelList.add(currentChannel);
-            mViewType[index++] = R.layout.menu_card_app_link;
-        }
-        for ( ; index < mViewType.length; ++index) {
-            mViewType[index] = R.layout.menu_card_channel;
-        }
-        channelList.addAll(getRecentChannels());
-        setItemList(channelList);
+    private boolean needToShowAppLinkItem() {
+        TvInputManagerHelper inputManager =
+                TvApplication.getSingletons(mContext).getTvInputManagerHelper();
+        Channel currentChannel = getMainActivity().getCurrentChannel();
+        return currentChannel != null
+                && currentChannel.getAppLinkType(mContext) != Channel.APP_LINK_TYPE_NONE
+                // Sometimes applicationInfo can be null. b/28932537
+                && inputManager.getTvInputAppInfo(currentChannel.getInputId()) != null;
     }
 
     private List<Channel> getRecentChannels() {
         List<Channel> channelList = new ArrayList<>();
-        for (Channel channel : mRecommender.recommendChannels(mMaxCount)) {
-            if (channel.isBrowsable()) {
-                channelList.add(channel);
+        long currentChannelId = getMainActivity().getCurrentChannelId();
+        ArrayDeque<Long> recentChannels = getMainActivity().getRecentChannels();
+        // Add the last watched channel as the first one.
+        for (long channelId : recentChannels) {
+            if (addChannelToList(
+                    channelList, mRecommender.getChannel(channelId), currentChannelId)) {
+                break;
             }
         }
-        int count = channelList.size();
+        // Add the recommended channels.
+        for (Channel channel : mRecommender.recommendChannels(mMaxCount)) {
+            if (channelList.size() >= mMaxCount) {
+                break;
+            }
+            addChannelToList(channelList, channel, currentChannelId);
+        }
         // If the number of recommended channels is not enough, add more from the recent channel
         // list.
-        if (count < mMinCount) {
-            for (long channelId : getMainActivity().getRecentChannels()) {
-                Channel channel = mRecommender.getChannel(channelId);
-                if (channel == null || channelList.contains(channel)
-                        || !channel.isBrowsable()) {
-                   continue;
-                }
-                channelList.add(channel);
-                if (++count >= mMinCount) {
-                    break;
-                }
+        for (long channelId : recentChannels) {
+            if (channelList.size() >= mMinCount) {
+                break;
             }
+            addChannelToList(channelList, mRecommender.getChannel(channelId), currentChannelId);
         }
         return channelList;
     }
+
+    private static boolean addChannelToList(
+            List<Channel> channelList, Channel channel, long currentChannelId) {
+        if (channel == null || channel.getId() == currentChannelId
+                || channelList.contains(channel) || !channel.isBrowsable()) {
+            return false;
+        }
+        channelList.add(channel);
+        return true;
+    }
 }
diff --git a/src/com/android/tv/menu/ChannelsRowItem.java b/src/com/android/tv/menu/ChannelsRowItem.java
new file mode 100644
index 0000000..c35189e
--- /dev/null
+++ b/src/com/android/tv/menu/ChannelsRowItem.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2017 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.menu;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+import com.android.tv.R;
+import com.android.tv.data.Channel;
+
+/**
+ * A class for the items in channels row.
+ */
+public class ChannelsRowItem {
+    /** The item ID for guide item */
+    public static final int GUIDE_ITEM_ID = -1;
+    /** The item ID for setup item */
+    public static final int SETUP_ITEM_ID = -2;
+    /** The item ID for DVR item */
+    public static final int DVR_ITEM_ID = -3;
+    /** The item ID for app link item */
+    public static final int APP_LINK_ITEM_ID = -4;
+
+    /** The item which represents the guide. */
+    public static final ChannelsRowItem GUIDE_ITEM =
+            new ChannelsRowItem(GUIDE_ITEM_ID, R.layout.menu_card_guide);
+    /** The item which represents the setup. */
+    public static final ChannelsRowItem SETUP_ITEM =
+            new ChannelsRowItem(SETUP_ITEM_ID, R.layout.menu_card_setup);
+    /** The item which represents the DVR. */
+    public static final ChannelsRowItem DVR_ITEM =
+            new ChannelsRowItem(DVR_ITEM_ID, R.layout.menu_card_dvr);
+    /** The item which represents the app link. */
+    public static final ChannelsRowItem APP_LINK_ITEM =
+            new ChannelsRowItem(APP_LINK_ITEM_ID, R.layout.menu_card_app_link);
+
+    private final long mItemId;
+    @NonNull private Channel mChannel;
+    private final int mLayoutId;
+
+    public ChannelsRowItem(@NonNull Channel channel, int layoutId) {
+        this(channel.getId(), layoutId);
+        mChannel = channel;
+    }
+
+    private ChannelsRowItem(long itemId, int layoutId) {
+        mItemId = itemId;
+        mLayoutId = layoutId;
+    }
+
+    /**
+     * Returns the channel for this item.
+     */
+    @NonNull
+    public Channel getChannel() {
+        return mChannel;
+    }
+
+    /**
+     * Sets the channel.
+     */
+    public void setChannel(@NonNull Channel channel) {
+        mChannel = channel;
+    }
+
+    /**
+     * Returns the layout resource ID to represent this item.
+     */
+    public int getLayoutId() {
+        return mLayoutId;
+    }
+
+    /**
+     * Returns the unique ID for this item.
+     */
+    public long getItemId() {
+        return mItemId;
+    }
+
+    @Override
+    public String toString() {
+        return "ChannelsRowItem{"
+                + "itemId=" + mItemId
+                + ", layoutId=" + mLayoutId
+                + ", channel=" + mChannel + "}";
+    }
+}
diff --git a/src/com/android/tv/menu/ItemListRowView.java b/src/com/android/tv/menu/ItemListRowView.java
index 4919c59..cbeee93 100644
--- a/src/com/android/tv/menu/ItemListRowView.java
+++ b/src/com/android/tv/menu/ItemListRowView.java
@@ -28,6 +28,7 @@
 
 import com.android.tv.MainActivity;
 import com.android.tv.R;
+import com.android.tv.util.ViewCache;
 
 import java.util.Collections;
 import java.util.List;
@@ -69,6 +70,8 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mListView = (HorizontalGridView) getContentsView();
+        // Disable the position change animation of the cards.
+        mListView.setItemAnimator(null);
     }
 
     @Override
@@ -194,9 +197,24 @@
             return mItemList.size();
         }
 
+        /**
+         * Returns the position of the item.
+         */
+        protected int getItemPosition(T item) {
+            return mItemList.indexOf(item);
+        }
+
+        /**
+         * Returns {@code true} if the item list contains the item, otherwise {@code false}.
+         */
+        protected boolean containsItem(T item) {
+            return mItemList.contains(item);
+        }
+
         @Override
         public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
-            View view = mLayoutInflater.inflate(getLayoutResId(viewType), parent, false);
+            View view = ViewCache.getInstance().getOrCreateView(
+                    mLayoutInflater, getLayoutResId(viewType), parent);
             return new MyViewHolder(view);
         }
 
diff --git a/src/com/android/tv/menu/Menu.java b/src/com/android/tv/menu/Menu.java
index 1160a5b..e373de6 100644
--- a/src/com/android/tv/menu/Menu.java
+++ b/src/com/android/tv/menu/Menu.java
@@ -26,24 +26,28 @@
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.VisibleForTesting;
+import android.support.v17.leanback.widget.HorizontalGridView;
 import android.util.Log;
 
 import com.android.tv.ChannelTuner;
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.analytics.DurationTimer;
+import com.android.tv.TvOptionsManager;
 import com.android.tv.analytics.Tracker;
 import com.android.tv.common.TvCommonUtils;
 import com.android.tv.common.WeakHandler;
 import com.android.tv.menu.MenuRowFactory.PartnerRow;
-import com.android.tv.menu.MenuRowFactory.PipOptionsRow;
 import com.android.tv.menu.MenuRowFactory.TvOptionsRow;
 import com.android.tv.ui.TunableTvView;
+import com.android.tv.util.DurationTimer;
+import com.android.tv.util.ViewCache;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * A class which controls the menu.
@@ -81,10 +85,21 @@
         sRowIdListForReason.add(PlayControlsRow.ID); // REASON_PLAY_CONTROLS_JUMP_TO_NEXT
     }
 
+    private static final Map<Integer, Integer> PRELOAD_VIEW_IDS = new HashMap<>();
+    static {
+        PRELOAD_VIEW_IDS.put(R.layout.menu_card_guide, 1);
+        PRELOAD_VIEW_IDS.put(R.layout.menu_card_setup, 1);
+        PRELOAD_VIEW_IDS.put(R.layout.menu_card_dvr, 1);
+        PRELOAD_VIEW_IDS.put(R.layout.menu_card_app_link, 1);
+        PRELOAD_VIEW_IDS.put(R.layout.menu_card_channel, ChannelsRow.MAX_COUNT_FOR_RECENT_CHANNELS);
+        PRELOAD_VIEW_IDS.put(R.layout.menu_card_action, 7);
+    }
+
     private static final String SCREEN_NAME = "Menu";
 
     private static final int MSG_HIDE_MENU = 1000;
 
+    private final Context mContext;
     private final IMenuView mMenuView;
     private final Tracker mTracker;
     private final DurationTimer mVisibleTimer = new DurationTimer();
@@ -103,15 +118,16 @@
     @VisibleForTesting
     Menu(Context context, IMenuView menuView, MenuRowFactory menuRowFactory,
             OnMenuVisibilityChangeListener onMenuVisibilityChangeListener) {
-        this(context, null, menuView, menuRowFactory, onMenuVisibilityChangeListener);
+        this(context, null, null, menuView, menuRowFactory, onMenuVisibilityChangeListener);
     }
 
-    public Menu(Context context, TunableTvView tvView, IMenuView menuView,
-            MenuRowFactory menuRowFactory,
+    public Menu(Context context, TunableTvView tvView, TvOptionsManager optionsManager,
+            IMenuView menuView, MenuRowFactory menuRowFactory,
             OnMenuVisibilityChangeListener onMenuVisibilityChangeListener) {
+        mContext = context;
         mMenuView = menuView;
         mTracker = TvApplication.getSingletons(context).getTracker();
-        mMenuUpdater = new MenuUpdater(context, tvView, this);
+        mMenuUpdater = new MenuUpdater(this, tvView, optionsManager);
         Resources res = context.getResources();
         mShowDurationMillis = res.getInteger(R.integer.menu_show_duration);
         mOnMenuVisibilityChangeListener = onMenuVisibilityChangeListener;
@@ -130,7 +146,6 @@
         addMenuRow(menuRowFactory.createMenuRow(this, ChannelsRow.class));
         addMenuRow(menuRowFactory.createMenuRow(this, PartnerRow.class));
         addMenuRow(menuRowFactory.createMenuRow(this, TvOptionsRow.class));
-        addMenuRow(menuRowFactory.createMenuRow(this, PipOptionsRow.class));
         mMenuView.setMenuRows(mMenuRows);
     }
 
@@ -160,6 +175,16 @@
     }
 
     /**
+     * Preloads the item view used for the menu.
+     */
+    public void preloadItemViews() {
+        HorizontalGridView fakeParent = new HorizontalGridView(mContext);
+        for (int id : PRELOAD_VIEW_IDS.keySet()) {
+            ViewCache.getInstance().putView(mContext, id, fakeParent, PRELOAD_VIEW_IDS.get(id));
+        }
+    }
+
+    /**
      * Shows the main menu.
      *
      * @param reason A reason why this is called. See {@link MenuShowReason}
@@ -293,9 +318,7 @@
      */
     public void onStreamInfoChanged() {
         if (DEBUG) Log.d(TAG, "update options row in main menu");
-        for (MenuRow row : mMenuRows) {
-            row.onStreamInfoChanged();
-        }
+        mMenuUpdater.onStreamInfoChanged();
     }
 
     @VisibleForTesting
diff --git a/src/com/android/tv/menu/MenuAction.java b/src/com/android/tv/menu/MenuAction.java
index 0d59552..b435605 100644
--- a/src/com/android/tv/menu/MenuAction.java
+++ b/src/com/android/tv/menu/MenuAction.java
@@ -20,9 +20,9 @@
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 
-import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.TvOptionsManager;
+import com.android.tv.TvOptionsManager.OptionType;
 
 /**
  * A class to define possible actions from main menu.
@@ -36,12 +36,9 @@
     public static final MenuAction SELECT_DISPLAY_MODE_ACTION =
             new MenuAction(R.string.options_item_display_mode, TvOptionsManager.OPTION_DISPLAY_MODE,
                     R.drawable.ic_tvoption_aspect);
-    public static final MenuAction PIP_IN_APP_ACTION =
-            new MenuAction(R.string.options_item_pip, TvOptionsManager.OPTION_IN_APP_PIP,
-                    R.drawable.ic_tvoption_pip);
     public static final MenuAction SYSTEMWIDE_PIP_ACTION =
             new MenuAction(R.string.options_item_pip, TvOptionsManager.OPTION_SYSTEMWIDE_PIP,
-                    R.drawable.ic_pip_option_layout2);
+                    R.drawable.ic_tvoption_pip);
     public static final MenuAction SELECT_AUDIO_LANGUAGE_ACTION =
             new MenuAction(R.string.options_item_multi_audio, TvOptionsManager.OPTION_MULTI_AUDIO,
                     R.drawable.ic_tvoption_multi_track);
@@ -51,34 +48,36 @@
     public static final MenuAction DEV_ACTION =
             new MenuAction(R.string.options_item_developer,
                     TvOptionsManager.OPTION_DEVELOPER, R.drawable.ic_developer_mode_tv_white_48dp);
-    // TODO: Change the icon.
     public static final MenuAction SETTINGS_ACTION =
             new MenuAction(R.string.options_item_settings, TvOptionsManager.OPTION_SETTINGS,
                     R.drawable.ic_settings);
-    // Actions in the PIP option row.
-    public static final MenuAction PIP_SELECT_INPUT_ACTION =
-            new MenuAction(R.string.pip_options_item_source, TvOptionsManager.OPTION_PIP_INPUT,
-                    R.drawable.ic_pip_option_input);
-    public static final MenuAction PIP_SWAP_ACTION =
-            new MenuAction(R.string.pip_options_item_swap, TvOptionsManager.OPTION_PIP_SWAP,
-                    R.drawable.ic_pip_option_swap);
-    public static final MenuAction PIP_SOUND_ACTION =
-            new MenuAction(R.string.pip_options_item_sound, TvOptionsManager.OPTION_PIP_SOUND,
-                    R.drawable.ic_pip_option_swap_audio);
-    public static final MenuAction PIP_LAYOUT_ACTION =
-            new MenuAction(R.string.pip_options_item_layout, TvOptionsManager.OPTION_PIP_LAYOUT,
-                    R.drawable.ic_pip_option_layout1);
-    public static final MenuAction PIP_SIZE_ACTION =
-            new MenuAction(R.string.pip_options_item_size, TvOptionsManager.OPTION_PIP_SIZE,
-                    R.drawable.ic_pip_option_size);
 
     private final String mActionName;
     private final int mActionNameResId;
-    private final int mType;
+    @OptionType private final int mType;
+    private String mActionDescription;
     private Drawable mDrawable;
     private int mDrawableResId;
     private boolean mEnabled = true;
 
+    /**
+     * Sets the action description. Returns {@code trye} if the description is changed.
+     */
+    public static boolean setActionDescription(MenuAction action, String actionDescription) {
+        String oldDescription = action.mActionDescription;
+        action.mActionDescription = actionDescription;
+        return !TextUtils.equals(action.mActionDescription, oldDescription);
+    }
+
+    /**
+     * Enables or disables the action. Returns {@code true} if the value is changed.
+     */
+    public static boolean setEnabled(MenuAction action, boolean enabled) {
+        boolean changed = action.mEnabled != enabled;
+        action.mEnabled = enabled;
+        return changed;
+    }
+
     public MenuAction(int actionNameResId, int type, int drawableResId) {
         mActionName = null;
         mActionNameResId = actionNameResId;
@@ -102,11 +101,11 @@
         return context.getString(mActionNameResId);
     }
 
-    public String getActionDescription(Context context) {
-        return ((MainActivity) context).getTvOptionsManager().getOptionString(mType);
+    public String getActionDescription() {
+        return mActionDescription;
     }
 
-    public int getType() {
+    @OptionType public int getType() {
         return mType;
     }
 
@@ -120,28 +119,10 @@
         return mDrawable;
     }
 
-    /**
-     * Sets drawable resource id.
-     *
-     * @return {@code true} if drawable is changed.
-     */
-    public boolean setDrawableResId(int resId) {
-        if (mDrawableResId == resId) {
-            return false;
-        }
-        mDrawable = null;
-        mDrawableResId = resId;
-        return true;
-    }
-
     public boolean isEnabled() {
         return mEnabled;
     }
 
-    public void setEnabled(boolean enabled) {
-        mEnabled = enabled;
-    }
-
     public int getActionNameResId() {
         return mActionNameResId;
     }
diff --git a/src/com/android/tv/menu/MenuLayoutManager.java b/src/com/android/tv/menu/MenuLayoutManager.java
index 6c76724..173d400 100644
--- a/src/com/android/tv/menu/MenuLayoutManager.java
+++ b/src/com/android/tv/menu/MenuLayoutManager.java
@@ -28,6 +28,7 @@
 import android.support.v4.view.animation.FastOutLinearInInterpolator;
 import android.support.v4.view.animation.FastOutSlowInInterpolator;
 import android.support.v4.view.animation.LinearOutSlowInInterpolator;
+import android.support.v7.widget.RecyclerView;
 import android.util.Log;
 import android.util.Property;
 import android.view.View;
@@ -56,12 +57,14 @@
 
     // The visible duration of the title before it is hidden.
     private static final long TITLE_SHOW_DURATION_BEFORE_HIDDEN_MS = TimeUnit.SECONDS.toMillis(2);
+    private static final int INVALID_POSITION = -1;
 
     private final MenuView mMenuView;
     private final List<MenuRow> mMenuRows = new ArrayList<>();
     private final List<MenuRowView> mMenuRowViews = new ArrayList<>();
     private final List<Integer> mRemovingRowViews = new ArrayList<>();
-    private int mSelectedPosition = -1;
+    private int mSelectedPosition = INVALID_POSITION;
+    private int mPendingSelectedPosition = INVALID_POSITION;
 
     private final int mRowAlignFromBottom;
     private final int mRowContentsPaddingTop;
@@ -130,8 +133,8 @@
         MenuRowView currentView = mMenuRowViews.get(mSelectedPosition);
         if (currentView.getVisibility() == View.GONE) {
             // If the selected row is not visible, select the first visible row.
-            int firstVisiblePosition = findNextVisiblePosition(-1);
-            if (firstVisiblePosition != -1) {
+            int firstVisiblePosition = findNextVisiblePosition(INVALID_POSITION);
+            if (firstVisiblePosition != INVALID_POSITION) {
                 mSelectedPosition = firstVisiblePosition;
             } else {
                 // No rows are visible.
@@ -157,6 +160,10 @@
                 view.onDeselected();
             }
         }
+
+        if (mPendingSelectedPosition != INVALID_POSITION) {
+            setSelectedPositionSmooth(mPendingSelectedPosition);
+        }
     }
 
     private int findNextVisiblePosition(int start) {
@@ -166,7 +173,7 @@
                 return i;
             }
         }
-        return -1;
+        return INVALID_POSITION;
     }
 
     private void dumpChildren(String prefix) {
@@ -327,6 +334,7 @@
             mMenuRowViews.get(mSelectedPosition).onDeselected();
         }
         mSelectedPosition = position;
+        mPendingSelectedPosition = INVALID_POSITION;
         if (Utils.isIndexValid(mMenuRowViews, mSelectedPosition)) {
             mMenuRowViews.get(mSelectedPosition).onSelected(false);
         }
@@ -380,14 +388,29 @@
             // again from the intermediate state.
             mTitleFadeOutAnimator.cancel();
         }
-        final int oldPosition = mSelectedPosition;
-        mSelectedPosition = position;
         if (DEBUG) dumpChildren("startRowAnimation()");
 
-        MenuRowView currentView = mMenuRowViews.get(position);
         // Show the children of the next row.
-        currentView.getTitleView().setVisibility(View.VISIBLE);
-        currentView.getContentsView().setVisibility(View.VISIBLE);
+        final MenuRowView currentView = mMenuRowViews.get(position);
+        TextView currentTitleView = currentView.getTitleView();
+        View currentContentsView = currentView.getContentsView();
+        currentTitleView.setVisibility(View.VISIBLE);
+        currentContentsView.setVisibility(View.VISIBLE);
+        if (currentView instanceof PlayControlsRowView) {
+            ((PlayControlsRowView) currentView).onPreselected();
+        }
+        // When contents view's visibility is gone, layouting might be delayed until it's shown and
+        // thus cause onBindViewHolder() and menu action updating occurs in front of users' sight.
+        // Therefore we call requestLayout() here if there are pending adapter updates.
+        if (currentContentsView instanceof RecyclerView
+                && ((RecyclerView) currentContentsView).hasPendingAdapterUpdates()) {
+            currentContentsView.requestLayout();
+            mPendingSelectedPosition = position;
+            return;
+        }
+        final int oldPosition = mSelectedPosition;
+        mSelectedPosition = position;
+        mPendingSelectedPosition = INVALID_POSITION;
         // Request focus after the new contents view shows up.
         mMenuView.requestFocus();
         if (mTempTitleViewForOld == null) {
@@ -407,7 +430,7 @@
 
         // Old row.
         MenuRow oldRow = mMenuRows.get(oldPosition);
-        MenuRowView oldView = mMenuRowViews.get(oldPosition);
+        final MenuRowView oldView = mMenuRowViews.get(oldPosition);
         View oldContentsView = oldView.getContentsView();
         // Old contents view.
         animators.add(createAlphaAnimator(oldContentsView, 1.0f, 0.0f, 1.0f, mLinearOutSlowIn)
@@ -468,8 +491,6 @@
         }
         // Current row.
         Rect currentLayoutRect = new Rect(layouts.get(position));
-        TextView currentTitleView = currentView.getTitleView();
-        View currentContentsView = currentView.getContentsView();
         currentContentsView.setAlpha(0.0f);
         if (scrollDown) {
             // Current title view.
@@ -529,7 +550,7 @@
         int nextPosition;
         if (scrollDown) {
             nextPosition = findNextVisiblePosition(position);
-            if (nextPosition != -1) {
+            if (nextPosition != INVALID_POSITION) {
                 MenuRowView nextView = mMenuRowViews.get(nextPosition);
                 Rect nextLayoutRect = layouts.get(nextPosition);
                 animators.add(createTranslationYAnimator(nextView,
@@ -539,7 +560,7 @@
             }
         } else {
             nextPosition = findNextVisiblePosition(oldPosition);
-            if (nextPosition != -1) {
+            if (nextPosition != INVALID_POSITION) {
                 MenuRowView nextView = mMenuRowViews.get(nextPosition);
                 animators.add(createTranslationYAnimator(nextView, 0, mRowScrollUpAnimationOffset));
                 animators.add(createAlphaAnimator(nextView,
@@ -572,9 +593,8 @@
                 for (ViewPropertyValueHolder holder : propertyValuesAfterAnimation) {
                     holder.property.set(holder.view, holder.value);
                 }
-                oldTitleView.setVisibility(View.VISIBLE);
-                mMenuRowViews.get(oldPosition).onDeselected();
-                mMenuRowViews.get(position).onSelected(true);
+                oldView.onDeselected();
+                currentView.onSelected(true);
                 mTempTitleViewForOld.setVisibility(View.GONE);
                 mTempTitleViewForCurrent.setVisibility(View.GONE);
                 layout(mMenuView.getLeft(), mMenuView.getTop(), mMenuView.getRight(),
diff --git a/src/com/android/tv/menu/MenuRow.java b/src/com/android/tv/menu/MenuRow.java
index 6f98e61..47804f1 100644
--- a/src/com/android/tv/menu/MenuRow.java
+++ b/src/com/android/tv/menu/MenuRow.java
@@ -123,11 +123,6 @@
     public void onRecentChannelsChanged() { }
 
     /**
-     * This method is called when stream information is changed.
-     */
-    public void onStreamInfoChanged() { }
-
-    /**
      * Returns whether to hide the title when the row is selected.
      */
     public boolean hideTitleWhenSelected() {
diff --git a/src/com/android/tv/menu/MenuRowFactory.java b/src/com/android/tv/menu/MenuRowFactory.java
index c67a0e0..570cfb8 100644
--- a/src/com/android/tv/menu/MenuRowFactory.java
+++ b/src/com/android/tv/menu/MenuRowFactory.java
@@ -67,8 +67,6 @@
         } else if (TvOptionsRow.class.equals(key)) {
             return new TvOptionsRow(mMainActivity, menu, mTvCustomizationManager
                     .getCustomActions(TvCustomizationManager.ID_OPTIONS_ROW));
-        } else if (PipOptionsRow.class.equals(key)) {
-            return new PipOptionsRow(mMainActivity, menu);
         }
         return null;
     }
@@ -77,36 +75,15 @@
      * A menu row which represents the TV options row.
      */
     public static class TvOptionsRow extends ItemListRow {
+        /**
+         * The ID of the row.
+         */
+        public static final String ID = TvOptionsRow.class.getName();
+
         private TvOptionsRow(Context context, Menu menu, List<CustomAction> customActions) {
             super(context, menu, R.string.menu_title_options, R.dimen.action_card_height,
                     new TvOptionsRowAdapter(context, customActions));
         }
-
-        @Override
-        public void onStreamInfoChanged() {
-            if (getMenu().isActive()) {
-                update();
-            }
-        }
-    }
-
-    /**
-     * A menu row which represents the PIP options row.
-     */
-    public static class PipOptionsRow extends ItemListRow {
-        private final MainActivity mMainActivity;
-
-        private PipOptionsRow(Context context, Menu menu) {
-            super(context, menu, R.string.menu_title_pip_options, R.dimen.action_card_height,
-                    new PipOptionsRowAdapter(context));
-            mMainActivity = (MainActivity) context;
-        }
-
-        @Override
-        public boolean isVisible() {
-            // TODO: Remove the dependency on MainActivity.
-            return super.isVisible() && mMainActivity.isPipEnabled();
-        }
     }
 
     /**
diff --git a/src/com/android/tv/menu/MenuUpdater.java b/src/com/android/tv/menu/MenuUpdater.java
index 075b299..18416c8 100644
--- a/src/com/android/tv/menu/MenuUpdater.java
+++ b/src/com/android/tv/menu/MenuUpdater.java
@@ -16,11 +16,14 @@
 
 package com.android.tv.menu;
 
-import android.content.Context;
 import android.support.annotation.Nullable;
 
 import com.android.tv.ChannelTuner;
+import com.android.tv.TvOptionsManager;
+import com.android.tv.TvOptionsManager.OptionChangedListener;
+import com.android.tv.TvOptionsManager.OptionType;
 import com.android.tv.data.Channel;
+import com.android.tv.menu.MenuRowFactory.TvOptionsRow;
 import com.android.tv.ui.TunableTvView;
 import com.android.tv.ui.TunableTvView.OnScreenBlockingChangedListener;
 
@@ -30,10 +33,10 @@
  * <p>As the menu is updated when it shows up, this class handles only the dynamic updates.
  */
 public class MenuUpdater {
-    // Can be null for testing.
-    @Nullable
-    private final TunableTvView mTvView;
     private final Menu mMenu;
+    // Can be null for testing.
+    @Nullable private final TunableTvView mTvView;
+    @Nullable private final TvOptionsManager mOptionsManager;
     private ChannelTuner mChannelTuner;
 
     private final ChannelTuner.Listener mChannelTunerListener = new ChannelTuner.Listener() {
@@ -42,7 +45,7 @@
 
         @Override
         public void onBrowsableChannelListChanged() {
-            mMenu.update();
+            mMenu.update(ChannelsRow.ID);
         }
 
         @Override
@@ -53,10 +56,17 @@
             mMenu.update(ChannelsRow.ID);
         }
     };
+    private final OptionChangedListener mOptionChangeListener = new OptionChangedListener() {
+        @Override
+        public void onOptionChanged(@OptionType int optionType, String newString) {
+            mMenu.update(TvOptionsRow.ID);
+        }
+    };
 
-    public MenuUpdater(Context context, TunableTvView tvView, Menu menu) {
-        mTvView = tvView;
+    public MenuUpdater(Menu menu, TunableTvView tvView, TvOptionsManager optionsManager) {
         mMenu = menu;
+        mTvView = tvView;
+        mOptionsManager = optionsManager;
         if (mTvView != null) {
             mTvView.setOnScreenBlockedListener(new OnScreenBlockingChangedListener() {
                     @Override
@@ -65,11 +75,18 @@
                     }
             });
         }
+        if (mOptionsManager != null) {
+            mOptionsManager.setOptionChangedListener(TvOptionsManager.OPTION_CLOSED_CAPTIONS,
+                    mOptionChangeListener);
+            mOptionsManager.setOptionChangedListener(TvOptionsManager.OPTION_DISPLAY_MODE,
+                    mOptionChangeListener);
+            mOptionsManager.setOptionChangedListener(TvOptionsManager.OPTION_MULTI_AUDIO,
+                    mOptionChangeListener);
+        }
     }
 
     /**
-     * Sets the instance of {@link ChannelTuner}. Call this method when the channel tuner is ready
-     * or not available any more.
+     * Sets the instance of {@link ChannelTuner}. Call this method when the channel tuner is ready.
      */
     public void setChannelTuner(ChannelTuner channelTuner) {
         if (mChannelTuner != null) {
@@ -79,7 +96,13 @@
         if (mChannelTuner != null) {
             mChannelTuner.addListener(mChannelTunerListener);
         }
-        mMenu.update();
+    }
+
+    /**
+     * Called when the stream information changes.
+     */
+    public void onStreamInfoChanged() {
+        mMenu.update(TvOptionsRow.ID);
     }
 
     /**
@@ -92,5 +115,10 @@
         if (mTvView != null) {
             mTvView.setOnScreenBlockedListener(null);
         }
+        if (mOptionsManager != null) {
+            mOptionsManager.setOptionChangedListener(TvOptionsManager.OPTION_CLOSED_CAPTIONS, null);
+            mOptionsManager.setOptionChangedListener(TvOptionsManager.OPTION_DISPLAY_MODE, null);
+            mOptionsManager.setOptionChangedListener(TvOptionsManager.OPTION_MULTI_AUDIO, null);
+        }
     }
 }
diff --git a/src/com/android/tv/menu/OptionsRowAdapter.java b/src/com/android/tv/menu/OptionsRowAdapter.java
index 93bd0a4..dd6194a 100644
--- a/src/com/android/tv/menu/OptionsRowAdapter.java
+++ b/src/com/android/tv/menu/OptionsRowAdapter.java
@@ -21,8 +21,6 @@
 
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.TvOptionsManager;
-import com.android.tv.TvOptionsManager.OptionChangedListener;
 import com.android.tv.analytics.Tracker;
 
 import java.util.List;
@@ -66,12 +64,9 @@
     public void update() {
         if (mActionList == null) {
             mActionList = createActions();
-            updateActions();
             setItemList(mActionList);
         } else {
-            if (updateActions()) {
-                setItemList(mActionList);
-            }
+            updateActions();
         }
     }
 
@@ -81,7 +76,7 @@
     }
 
     protected abstract List<MenuAction> createActions();
-    protected abstract boolean updateActions();
+    protected abstract void updateActions();
     protected abstract void executeAction(int type);
 
     /**
@@ -93,37 +88,6 @@
         return mActionList.get(position);
     }
 
-    /**
-     * Sets the action at the given position.
-     * Note that action at the position may differ from returned by {@link #createActions}.
-     * See {@link CustomizableOptionsRowAdapter}
-     */
-    protected void setAction(int position, MenuAction action) {
-        mActionList.set(position, action);
-    }
-
-    /**
-     * Adds an action to the given position.
-     * Note that action at the position may differ from returned by {@link #createActions}.
-     * See {@link CustomizableOptionsRowAdapter}
-     */
-    protected void addAction(int position, MenuAction action) {
-        mActionList.add(position, action);
-    }
-
-    /**
-     * Removes an action at the given position.
-     * Note that action at the position may differ from returned by {@link #createActions}.
-     * See {@link CustomizableOptionsRowAdapter}
-     */
-    protected void removeAction(int position) {
-        mActionList.remove(position);
-    }
-
-    protected int getActionSize() {
-        return mActionList.size();
-    }
-
     @Override
     public void onBindViewHolder(MyViewHolder viewHolder, int position) {
         super.onBindViewHolder(viewHolder, position);
@@ -139,14 +103,4 @@
         // be preserved.
         return mActionList.get(position).getType();
     }
-
-    protected void setOptionChangedListener(final MenuAction action) {
-        TvOptionsManager om = getMainActivity().getTvOptionsManager();
-        om.setOptionChangedListener(action.getType(), new OptionChangedListener() {
-            @Override
-            public void onOptionChanged(String newOption) {
-                setItemList(mActionList);
-            }
-        });
-    }
 }
diff --git a/src/com/android/tv/menu/PartnerOptionsRowAdapter.java b/src/com/android/tv/menu/PartnerOptionsRowAdapter.java
index f3e09f8..c8249a4 100644
--- a/src/com/android/tv/menu/PartnerOptionsRowAdapter.java
+++ b/src/com/android/tv/menu/PartnerOptionsRowAdapter.java
@@ -38,8 +38,7 @@
     }
 
     @Override
-    protected boolean updateActions() {
+    protected void updateActions() {
         // TODO: Support adding description for custom actions.
-        return false;
     }
 }
diff --git a/src/com/android/tv/menu/PipOptionsRowAdapter.java b/src/com/android/tv/menu/PipOptionsRowAdapter.java
deleted file mode 100644
index 87203e9..0000000
--- a/src/com/android/tv/menu/PipOptionsRowAdapter.java
+++ /dev/null
@@ -1,137 +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.menu;
-
-import android.content.Context;
-import android.text.TextUtils;
-
-import com.android.tv.MainActivity;
-import com.android.tv.R;
-import com.android.tv.TvOptionsManager;
-import com.android.tv.ui.TvViewUiManager;
-import com.android.tv.ui.sidepanel.PipInputSelectorFragment;
-import com.android.tv.util.PipInputManager.PipInput;
-import com.android.tv.util.TvSettings;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/*
- * An adapter of PIP options.
- */
-public class PipOptionsRowAdapter extends OptionsRowAdapter {
-    private static final int[] DRAWABLE_ID_FOR_LAYOUT = {
-            R.drawable.ic_pip_option_layout1,
-            R.drawable.ic_pip_option_layout2,
-            R.drawable.ic_pip_option_layout3,
-            R.drawable.ic_pip_option_layout4,
-            R.drawable.ic_pip_option_layout5 };
-
-    private final TvOptionsManager mTvOptionsManager;
-    private final TvViewUiManager mTvViewUiManager;
-
-    public PipOptionsRowAdapter(Context context) {
-        super(context);
-        mTvOptionsManager = getMainActivity().getTvOptionsManager();
-        mTvViewUiManager = getMainActivity().getTvViewUiManager();
-    }
-
-    @Override
-    protected List<MenuAction> createActions() {
-        List<MenuAction> actionList = new ArrayList<>();
-        actionList.add(MenuAction.PIP_SELECT_INPUT_ACTION);
-        actionList.add(MenuAction.PIP_SWAP_ACTION);
-        actionList.add(MenuAction.PIP_SOUND_ACTION);
-        actionList.add(MenuAction.PIP_LAYOUT_ACTION);
-        actionList.add(MenuAction.PIP_SIZE_ACTION);
-        for (MenuAction action : actionList) {
-            setOptionChangedListener(action);
-        }
-        return actionList;
-    }
-
-    @Override
-    public boolean updateActions() {
-        boolean changed = false;
-        if (updateSelectInputAction()) {
-            changed = true;
-        }
-        if (updateLayoutAction()) {
-            changed = true;
-        }
-        if (updateSizeAction()) {
-            changed = true;
-        }
-        return changed;
-    }
-
-    private boolean updateSelectInputAction() {
-        String oldInputLabel = mTvOptionsManager.getOptionString(TvOptionsManager.OPTION_PIP_INPUT);
-
-        MainActivity tvActivity = getMainActivity();
-        PipInput newInput = tvActivity.getPipInputManager().getPipInput(tvActivity.getPipChannel());
-        String newInputLabel = newInput == null ? null : newInput.getLabel();
-
-        if (!TextUtils.equals(oldInputLabel, newInputLabel)) {
-            mTvOptionsManager.onPipInputChanged(newInputLabel);
-            return true;
-        }
-        return false;
-    }
-
-    private boolean updateLayoutAction() {
-        return MenuAction.PIP_LAYOUT_ACTION.setDrawableResId(
-            DRAWABLE_ID_FOR_LAYOUT[mTvViewUiManager.getPipLayout()]);
-    }
-
-    private boolean updateSizeAction() {
-        boolean oldEnabled = MenuAction.PIP_SIZE_ACTION.isEnabled();
-        boolean newEnabled = mTvViewUiManager.getPipLayout() != TvSettings.PIP_LAYOUT_SIDE_BY_SIDE;
-        if (oldEnabled != newEnabled) {
-            MenuAction.PIP_SIZE_ACTION.setEnabled(newEnabled);
-            return true;
-        }
-        return false;
-    }
-
-    @Override
-    protected void executeAction(int type) {
-        switch (type) {
-            case TvOptionsManager.OPTION_PIP_INPUT:
-                getMainActivity().getOverlayManager().getSideFragmentManager().show(
-                        new PipInputSelectorFragment());
-                break;
-            case TvOptionsManager.OPTION_PIP_SWAP:
-                getMainActivity().swapPip();
-                break;
-            case TvOptionsManager.OPTION_PIP_SOUND:
-                getMainActivity().togglePipSoundMode();
-                break;
-            case TvOptionsManager.OPTION_PIP_LAYOUT:
-                int oldLayout = mTvViewUiManager.getPipLayout();
-                int newLayout = (oldLayout + 1) % (TvSettings.PIP_LAYOUT_LAST + 1);
-                mTvViewUiManager.setPipLayout(newLayout, true);
-                MenuAction.PIP_LAYOUT_ACTION.setDrawableResId(DRAWABLE_ID_FOR_LAYOUT[newLayout]);
-                break;
-            case TvOptionsManager.OPTION_PIP_SIZE:
-                int oldSize = mTvViewUiManager.getPipSize();
-                int newSize = (oldSize + 1) % (TvSettings.PIP_SIZE_LAST + 1);
-                mTvViewUiManager.setPipSize(newSize, true);
-                break;
-        }
-    }
-}
diff --git a/src/com/android/tv/menu/PlayControlsButton.java b/src/com/android/tv/menu/PlayControlsButton.java
index aff39db..77715f2 100644
--- a/src/com/android/tv/menu/PlayControlsButton.java
+++ b/src/com/android/tv/menu/PlayControlsButton.java
@@ -39,6 +39,9 @@
     private final int mIconColor;
     private int mIconFocusedColor;
 
+    private int mImageResourceId;
+    private int mTintColor;
+
     public PlayControlsButton(Context context) {
         this(context, null);
     }
@@ -67,10 +70,21 @@
      * Sets the resource ID of the image to be displayed in the center of this control.
      */
     public void setImageResId(int imageResId) {
-        mIcon.setImageResource(imageResId);
-        // Since on foucus changing, icons' color should be switched with animation,
+        int newTintColor = hasFocus() ? mIconFocusedColor : mIconColor;
+        if (mImageResourceId != imageResId) {
+            mImageResourceId = imageResId;
+            mIcon.setImageResource(imageResId);
+            updateTint(newTintColor);
+        } else if (newTintColor != mTintColor) {
+            updateTint(newTintColor);
+        }
+    }
+
+    private void updateTint(int tintColor) {
+        mTintColor = tintColor;
+        // Since on focus changing, icons' color should be switched with animation,
         // as a result, selectors cannot be used to switch colors in this case.
-        mIcon.getDrawable().setTint(hasFocus() ? mIconFocusedColor : mIconColor);
+        mIcon.getDrawable().setTint(tintColor);
     }
 
     /**
@@ -117,7 +131,9 @@
         } else {
             mIcon.setVisibility(View.GONE);
             mLabel.setVisibility(View.VISIBLE);
-            mLabel.setText(label);
+            if (!TextUtils.equals(mLabel.getText(), label)) {
+                mLabel.setText(label);
+            }
         }
     }
 
diff --git a/src/com/android/tv/menu/PlayControlsRowView.java b/src/com/android/tv/menu/PlayControlsRowView.java
index a620d4d..4d76678 100644
--- a/src/com/android/tv/menu/PlayControlsRowView.java
+++ b/src/com/android/tv/menu/PlayControlsRowView.java
@@ -18,10 +18,10 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.TextView;
 import android.widget.Toast;
 
@@ -34,17 +34,16 @@
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.data.Channel;
 import com.android.tv.data.Program;
+import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dvr.DvrDataManager;
 import com.android.tv.dvr.DvrDataManager.OnDvrScheduleLoadFinishedListener;
 import com.android.tv.dvr.DvrDataManager.ScheduledRecordingListener;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.DvrUiHelper;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.dvr.ui.DvrStopRecordingFragment;
-import com.android.tv.dvr.ui.HalfSizedDialogFragment;
+import com.android.tv.dvr.ui.DvrUiHelper;
 import com.android.tv.menu.Menu.MenuShowReason;
 import com.android.tv.ui.TunableTvView;
-import com.android.tv.util.Utils;
 
 public class PlayControlsRowView extends MenuRowView {
     private static final int NORMAL_WIDTH_MAX_BUTTON_COUNT = 5;
@@ -53,14 +52,10 @@
     private final int mTimeTextLeftMargin;
     private final int mTimelineWidth;
     // Views
-    private View mBackgroundView;
+    private TextView mBackgroundView;
     private View mTimeIndicator;
     private TextView mTimeText;
-    private View mProgressEmptyBefore;
-    private View mProgressWatched;
-    private View mProgressBuffered;
-    private View mProgressEmptyAfter;
-    private View mControlBar;
+    private PlaybackProgressBar mProgress;
     private PlayControlsButton mJumpPreviousButton;
     private PlayControlsButton mRewindButton;
     private PlayControlsButton mPlayPauseButton;
@@ -69,7 +64,6 @@
     private PlayControlsButton mRecordButton;
     private TextView mProgramStartTimeText;
     private TextView mProgramEndTimeText;
-    private View mUnavailableMessageText;
     private TunableTvView mTvView;
     private TimeShiftManager mTimeShiftManager;
     private final DvrDataManager mDvrDataManager;
@@ -83,6 +77,8 @@
     private final int mNormalButtonMargin;
     private final int mCompactButtonMargin;
 
+    private final String mUnavailableMessage;
+
     private final ScheduledRecordingListener mScheduledRecordingListener
             = new ScheduledRecordingListener() {
         @Override
@@ -138,6 +134,7 @@
             mDvrManager = null;
         }
         mMainActivity = (MainActivity) context;
+        mUnavailableMessage = res.getString(R.string.play_controls_unavailable);
     }
 
     @Override
@@ -171,14 +168,10 @@
         super.onFinishInflate();
         // Clip the ViewGroup(body) to the rounded rectangle of outline.
         findViewById(R.id.body).setClipToOutline(true);
-        mBackgroundView = findViewById(R.id.background);
+        mBackgroundView = (TextView) findViewById(R.id.background);
         mTimeIndicator = findViewById(R.id.time_indicator);
         mTimeText = (TextView) findViewById(R.id.time_text);
-        mProgressEmptyBefore = findViewById(R.id.timeline_bg_start);
-        mProgressWatched = findViewById(R.id.watched);
-        mProgressBuffered = findViewById(R.id.buffered);
-        mProgressEmptyAfter = findViewById(R.id.timeline_bg_end);
-        mControlBar = findViewById(R.id.play_control_bar);
+        mProgress = (PlaybackProgressBar) findViewById(R.id.progress);
         mJumpPreviousButton = (PlayControlsButton) findViewById(R.id.jump_previous);
         mRewindButton = (PlayControlsButton) findViewById(R.id.rewind);
         mPlayPauseButton = (PlayControlsButton) findViewById(R.id.play_pause);
@@ -187,7 +180,6 @@
         mRecordButton = (PlayControlsButton) findViewById(R.id.record);
         mProgramStartTimeText = (TextView) findViewById(R.id.program_start_time);
         mProgramEndTimeText = (TextView) findViewById(R.id.program_end_time);
-        mUnavailableMessageText = findViewById(R.id.unavailable_text);
 
         initializeButton(mJumpPreviousButton, R.drawable.lb_ic_skip_previous,
                 R.string.play_controls_description_skip_previous, null, new Runnable() {
@@ -195,7 +187,7 @@
             public void run() {
                 if (mTimeShiftManager.isAvailable()) {
                     mTimeShiftManager.jumpToPrevious();
-                    updateControls();
+                    updateControls(true);
                 }
             }
         });
@@ -235,7 +227,7 @@
             public void run() {
                 if (mTimeShiftManager.isAvailable()) {
                     mTimeShiftManager.jumpToNext();
-                    updateControls();
+                    updateControls(true);
                 }
             }
         });
@@ -265,18 +257,17 @@
             if (!(mDvrManager != null && mDvrManager.isChannelRecordable(currentChannel))) {
                 Toast.makeText(mMainActivity, R.string.dvr_msg_cannot_record_channel,
                         Toast.LENGTH_SHORT).show();
-            } else if (DvrUiHelper.checkStorageStatusAndShowErrorMessage(mMainActivity,
-                    currentChannel.getInputId())) {
+            } else {
                 Program program = TvApplication.getSingletons(mMainActivity).getProgramDataManager()
                         .getCurrentProgram(currentChannel.getId());
-                if (program == null) {
-                    DvrUiHelper.showChannelRecordDurationOptions(mMainActivity, currentChannel);
-                } else if (DvrUiHelper.handleCreateSchedule(mMainActivity, program)) {
-                    String msg = mMainActivity.getString(R.string.dvr_msg_current_program_scheduled,
-                            program.getTitle(),
-                            Utils.toTimeString(program.getEndTimeUtcMillis(), false));
-                    Toast.makeText(mMainActivity, msg, Toast.LENGTH_SHORT).show();
-                }
+                DvrUiHelper.checkStorageStatusAndShowErrorMessage(mMainActivity,
+                        currentChannel.getInputId(), new Runnable() {
+                            @Override
+                            public void run() {
+                                DvrUiHelper.requestRecordingCurrentProgram(mMainActivity,
+                                        currentChannel, program, true);
+                            }
+                        });
             }
         } else if (currentChannel != null) {
             DvrUiHelper.showStopRecordingDialog(mMainActivity, currentChannel.getId(),
@@ -318,39 +309,37 @@
             @Override
             public void onAvailabilityChanged() {
                 updateMenuVisibility();
-                if (isShown()) {
-                    PlayControlsRowView.this.updateAll();
-                }
+                PlayControlsRowView.this.updateAll(false);
             }
 
             @Override
             public void onPlayStatusChanged(int status) {
                 updateMenuVisibility();
-                if (mTimeShiftManager.isAvailable() && isShown()) {
-                    updateControls();
+                if (mTimeShiftManager.isAvailable()) {
+                    updateControls(false);
                 }
             }
 
             @Override
             public void onRecordTimeRangeChanged() {
-                if (mTimeShiftManager.isAvailable() && isShown()) {
-                    updateControls();
+                if (mTimeShiftManager.isAvailable()) {
+                    updateControls(false);
                 }
             }
 
             @Override
             public void onCurrentPositionChanged() {
-                if (mTimeShiftManager.isAvailable() && isShown()) {
+                if (mTimeShiftManager.isAvailable()) {
                     initializeTimeline();
-                    updateControls();
+                    updateControls(false);
                 }
             }
 
             @Override
             public void onProgramInfoChanged() {
-                if (mTimeShiftManager.isAvailable() && isShown()) {
+                if (mTimeShiftManager.isAvailable()) {
                     initializeTimeline();
-                    updateControls();
+                    updateControls(false);
                 }
             }
 
@@ -372,7 +361,8 @@
                 }
             }
         });
-        updateAll();
+        // force update to initialize everything
+        updateAll(true);
     }
 
     private void initializeTimeline() {
@@ -380,6 +370,8 @@
                 mTimeShiftManager.getCurrentPositionMs());
         mProgramStartTimeMs = program.getStartTimeUtcMillis();
         mProgramEndTimeMs = program.getEndTimeUtcMillis();
+        mProgress.setMax(mProgramEndTimeMs - mProgramStartTimeMs);
+        updateRecTimeText();
         SoftPreconditions.checkArgument(mProgramStartTimeMs <= mProgramEndTimeMs);
     }
 
@@ -389,10 +381,13 @@
         getMenu().setKeepVisible(keepMenuVisible);
     }
 
+    public void onPreselected() {
+        updateControls(true);
+    }
+
     @Override
     public void onSelected(boolean showTitle) {
         super.onSelected(showTitle);
-        updateControls();
         postHideRippleAnimation();
     }
 
@@ -474,28 +469,32 @@
      * Updates the view contents. It is called from the PlayControlsRow.
      */
     public void update() {
-        updateAll();
+        updateAll(false);
     }
 
-    private void updateAll() {
+    private void updateAll(boolean forceUpdate) {
         if (mTimeShiftManager.isAvailable() && !mTvView.isScreenBlocked()) {
             setEnabled(true);
             initializeTimeline();
             mBackgroundView.setEnabled(true);
+            setTextIfNeeded(mBackgroundView, null);
         } else {
             setEnabled(false);
             mBackgroundView.setEnabled(false);
+            setTextIfNeeded(mBackgroundView, mUnavailableMessage);
         }
-        updateControls();
+        // force the controls be updated no matter it's visible or not.
+        updateControls(forceUpdate);
     }
 
-    private void updateControls() {
-        updateTime();
-        updateProgress();
-        updateRecTimeText();
-        updateButtons();
-        updateRecordButton();
-        updateButtonMargin();
+    private void updateControls(boolean forceUpdate) {
+        if (forceUpdate || getContentsView().isShown()) {
+            updateTime();
+            updateProgress();
+            updateButtons();
+            updateRecordButton();
+            updateButtonMargin();
+        }
     }
 
     private void updateTime() {
@@ -504,70 +503,39 @@
             mTimeIndicator.setVisibility(View.VISIBLE);
         } else {
             mTimeText.setVisibility(View.INVISIBLE);
-            mTimeIndicator.setVisibility(View.INVISIBLE);
+            mTimeIndicator.setVisibility(View.GONE);
             return;
         }
         long currentPositionMs = mTimeShiftManager.getCurrentPositionMs();
-        ViewGroup.MarginLayoutParams params =
-                (ViewGroup.MarginLayoutParams) mTimeText.getLayoutParams();
         int currentTimePositionPixel =
                 convertDurationToPixel(currentPositionMs - mProgramStartTimeMs);
-        params.leftMargin = currentTimePositionPixel + mTimeTextLeftMargin;
-        mTimeText.setLayoutParams(params);
-        mTimeText.setText(getTimeString(currentPositionMs));
-        params = (ViewGroup.MarginLayoutParams) mTimeIndicator.getLayoutParams();
-        params.leftMargin = currentTimePositionPixel + mTimeIndicatorLeftMargin;
-        mTimeIndicator.setLayoutParams(params);
+        mTimeText.setTranslationX(currentTimePositionPixel + mTimeTextLeftMargin);
+        setTextIfNeeded(mTimeText, getTimeString(currentPositionMs));
+        mTimeIndicator.setTranslationX(currentTimePositionPixel + mTimeIndicatorLeftMargin);
     }
 
     private void updateProgress() {
         if (isEnabled()) {
-            mProgressWatched.setVisibility(View.VISIBLE);
-            mProgressBuffered.setVisibility(View.VISIBLE);
-            mProgressEmptyAfter.setVisibility(View.VISIBLE);
-        } else {
-            mProgressWatched.setVisibility(View.INVISIBLE);
-            mProgressBuffered.setVisibility(View.INVISIBLE);
-            mProgressEmptyAfter.setVisibility(View.INVISIBLE);
-            if (mProgramStartTimeMs < mProgramEndTimeMs) {
-                layoutProgress(mProgressEmptyBefore, mProgramStartTimeMs, mProgramEndTimeMs);
-            } else {
-                // Not initialized yet.
-                layoutProgress(mProgressEmptyBefore, mTimelineWidth);
-            }
-            return;
-        }
-
-        long progressStartTimeMs = Math.min(mProgramEndTimeMs,
+            long progressStartTimeMs = Math.min(mProgramEndTimeMs,
                     Math.max(mProgramStartTimeMs, mTimeShiftManager.getRecordStartTimeMs()));
-        long currentPlayingTimeMs = Math.min(mProgramEndTimeMs,
+            long currentPlayingTimeMs = Math.min(mProgramEndTimeMs,
                     Math.max(mProgramStartTimeMs, mTimeShiftManager.getCurrentPositionMs()));
-        long progressEndTimeMs = Math.min(mProgramEndTimeMs,
+            long progressEndTimeMs = Math.min(mProgramEndTimeMs,
                     Math.max(mProgramStartTimeMs, mTimeShiftManager.getRecordEndTimeMs()));
-
-        layoutProgress(mProgressEmptyBefore, mProgramStartTimeMs, progressStartTimeMs);
-        layoutProgress(mProgressWatched, progressStartTimeMs, currentPlayingTimeMs);
-        layoutProgress(mProgressBuffered, currentPlayingTimeMs, progressEndTimeMs);
-    }
-
-    private void layoutProgress(View progress, long progressStartTimeMs, long progressEndTimeMs) {
-        layoutProgress(progress, Math.max(0,
-                convertDurationToPixel(progressEndTimeMs - progressStartTimeMs)) + 1);
-    }
-
-    private void layoutProgress(View progress, int width) {
-        ViewGroup.MarginLayoutParams params =
-                (ViewGroup.MarginLayoutParams) progress.getLayoutParams();
-        params.width = width;
-        progress.setLayoutParams(params);
+            mProgress.setProgressRange(progressStartTimeMs - mProgramStartTimeMs,
+                    progressEndTimeMs - mProgramStartTimeMs);
+            mProgress.setProgress(currentPlayingTimeMs - mProgramStartTimeMs);
+        } else {
+            mProgress.setProgressRange(0, 0);
+        }
     }
 
     private void updateRecTimeText() {
         if (isEnabled()) {
             mProgramStartTimeText.setVisibility(View.VISIBLE);
-            mProgramStartTimeText.setText(getTimeString(mProgramStartTimeMs));
+            setTextIfNeeded(mProgramStartTimeText, getTimeString(mProgramStartTimeMs));
             mProgramEndTimeText.setVisibility(View.VISIBLE);
-            mProgramEndTimeText.setText(getTimeString(mProgramEndTimeMs));
+            setTextIfNeeded(mProgramEndTimeText, getTimeString(mProgramEndTimeMs));
         } else {
             mProgramStartTimeText.setVisibility(View.GONE);
             mProgramEndTimeText.setVisibility(View.GONE);
@@ -576,11 +544,17 @@
 
     private void updateButtons() {
         if (isEnabled()) {
-            mControlBar.setVisibility(View.VISIBLE);
-            mUnavailableMessageText.setVisibility(View.GONE);
+            mPlayPauseButton.setVisibility(View.VISIBLE);
+            mJumpPreviousButton.setVisibility(View.VISIBLE);
+            mJumpNextButton.setVisibility(View.VISIBLE);
+            mRewindButton.setVisibility(View.VISIBLE);
+            mFastForwardButton.setVisibility(View.VISIBLE);
         } else {
-            mControlBar.setVisibility(View.INVISIBLE);
-            mUnavailableMessageText.setVisibility(View.VISIBLE);
+            mPlayPauseButton.setVisibility(View.GONE);
+            mJumpPreviousButton.setVisibility(View.GONE);
+            mJumpNextButton.setVisibility(View.GONE);
+            mRewindButton.setVisibility(View.GONE);
+            mFastForwardButton.setVisibility(View.GONE);
             return;
         }
 
@@ -622,6 +596,12 @@
     }
 
     private void updateRecordButton() {
+        if (isEnabled()) {
+            mRecordButton.setVisibility(VISIBLE);
+        } else {
+            mRecordButton.setVisibility(GONE);
+            return;
+        }
         if (!(mDvrManager != null
                 && mDvrManager.isChannelRecordable(mMainActivity.getCurrentChannel()))) {
             mRecordButton.setVisibility(View.GONE);
@@ -682,4 +662,10 @@
             mDvrDataManager.removeScheduledRecordingListener(mScheduledRecordingListener);
         }
     }
+
+    private void setTextIfNeeded(TextView textView, String text) {
+        if (!TextUtils.equals(textView.getText(), text)) {
+            textView.setText(text);
+        }
+    }
 }
diff --git a/src/com/android/tv/menu/PlaybackProgressBar.java b/src/com/android/tv/menu/PlaybackProgressBar.java
new file mode 100644
index 0000000..e8061bc
--- /dev/null
+++ b/src/com/android/tv/menu/PlaybackProgressBar.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2017 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.menu;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.android.tv.R;
+
+/**
+ * A progress bar control which has two progresses which start in the middle of the control.
+ */
+public class PlaybackProgressBar extends View {
+    private final LayerDrawable mProgressDrawable;
+    private final Drawable mPrimaryDrawable;
+    private final Drawable mSecondaryDrawable;
+    private long mMax = 100;
+    private long mProgressStart = 0;
+    private long mProgressEnd = 0;
+    private long mProgress = 0;
+
+    public PlaybackProgressBar(Context context) {
+        this(context, null);
+    }
+
+    public PlaybackProgressBar(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PlaybackProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public PlaybackProgressBar(Context context, AttributeSet attrs, int defStyleAttr,
+                               int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+        TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.PlaybackProgressBar, defStyleAttr, defStyleRes);
+        mProgressDrawable =
+                (LayerDrawable) a.getDrawable(R.styleable.PlaybackProgressBar_progressDrawable);
+        mPrimaryDrawable = mProgressDrawable.findDrawableByLayerId(android.R.id.progress);
+        mSecondaryDrawable =
+                mProgressDrawable.findDrawableByLayerId(android.R.id.secondaryProgress);
+        a.recycle();
+        refreshProgress();
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        final int saveCount = canvas.save();
+        canvas.translate(getPaddingLeft(), getPaddingTop());
+        mProgressDrawable.draw(canvas);
+        canvas.restoreToCount(saveCount);
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        refreshProgress();
+    }
+
+    public void setMax(long max) {
+        if (max < 0) {
+            max = 0;
+        }
+        if (max != mMax) {
+            mMax = max;
+            if (mProgressStart > max) {
+                mProgressStart = max;
+            }
+            if (mProgressEnd > max) {
+                mProgressEnd = max;
+            }
+            if (mProgress > max) {
+                mProgress = max;
+            }
+            refreshProgress();
+        }
+    }
+
+    /**
+     * Sets the start and end position of the progress.
+     */
+    public void setProgressRange(long start, long end) {
+        start = constrain(start, 0, mMax);
+        end = constrain(end, start, mMax);
+        mProgress = constrain(mProgress, start, end);
+        if (start != mProgressStart || end != mProgressEnd) {
+            mProgressStart = start;
+            mProgressEnd = end;
+            setProgressLevels();
+        }
+    }
+
+    /**
+     * Sets the progress position.
+     */
+    public void setProgress(long progress) {
+        progress = constrain(progress, mProgressStart, mProgressEnd);
+        if (progress != mProgress) {
+            mProgress = progress;
+            setProgressLevels();
+        }
+    }
+
+    private long constrain(long value, long min, long max) {
+        return Math.min(Math.max(value, min), max);
+    }
+
+    private void refreshProgress() {
+        int width = getWidth() - getPaddingStart() - getPaddingEnd();
+        int height = getHeight() - getPaddingTop() - getPaddingBottom();
+        mProgressDrawable.setBounds(0, 0, width, height);
+        setProgressLevels();
+    }
+
+    private void setProgressLevels() {
+        boolean progressUpdated = setProgressBound(mPrimaryDrawable, mProgressStart, mProgress);
+        progressUpdated |= setProgressBound(mSecondaryDrawable, mProgress, mProgressEnd);
+        if (progressUpdated) {
+            postInvalidate();
+        }
+    }
+
+    private boolean setProgressBound(Drawable drawable, long start, long end) {
+        Rect oldBounds = drawable.getBounds();
+        if (mMax == 0) {
+            if (!isEqualRect(oldBounds, 0, 0, 0, 0)) {
+                drawable.setBounds(0, 0, 0, 0);
+                return true;
+            }
+            return false;
+        }
+        int width = mProgressDrawable.getBounds().width();
+        int height = mProgressDrawable.getBounds().height();
+        int left = (int) (width * start / mMax);
+        int right = (int) (width * end / mMax);
+        if (!isEqualRect(oldBounds, left, 0, right, height)) {
+            drawable.setBounds(left, 0, right, height);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isEqualRect(Rect rect, int left, int top, int right, int bottom) {
+        return rect.left == left && rect.top == top && rect.right == right && rect.bottom == bottom;
+    }
+}
diff --git a/src/com/android/tv/menu/SimpleCardView.java b/src/com/android/tv/menu/SimpleCardView.java
index c99834b..fc5192d 100644
--- a/src/com/android/tv/menu/SimpleCardView.java
+++ b/src/com/android/tv/menu/SimpleCardView.java
@@ -19,12 +19,10 @@
 import android.content.Context;
 import android.util.AttributeSet;
 
-import com.android.tv.data.Channel;
-
 /**
  * A view to render a guide card.
  */
-public class SimpleCardView extends BaseCardView<Channel> {
+public class SimpleCardView extends BaseCardView<ChannelsRowItem> {
 
     public SimpleCardView(Context context) {
         this(context, null, 0);
diff --git a/src/com/android/tv/menu/TvOptionsRowAdapter.java b/src/com/android/tv/menu/TvOptionsRowAdapter.java
index fb06224..6e035f2 100644
--- a/src/com/android/tv/menu/TvOptionsRowAdapter.java
+++ b/src/com/android/tv/menu/TvOptionsRowAdapter.java
@@ -21,7 +21,6 @@
 import android.support.annotation.VisibleForTesting;
 
 import com.android.tv.Features;
-import com.android.tv.R;
 import com.android.tv.TvOptionsManager;
 import com.android.tv.customization.CustomAction;
 import com.android.tv.data.DisplayMode;
@@ -30,7 +29,7 @@
 import com.android.tv.ui.sidepanel.DeveloperOptionFragment;
 import com.android.tv.ui.sidepanel.DisplayModeFragment;
 import com.android.tv.ui.sidepanel.MultiAudioFragment;
-import com.android.tv.util.PipInputManager;
+import com.android.tv.util.Utils;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -39,12 +38,6 @@
  * An adapter of options.
  */
 public class TvOptionsRowAdapter extends CustomizableOptionsRowAdapter {
-    private static final boolean ENABLE_IN_APP_PIP = false;
-
-    private int mPositionPipAction;
-    // If mInAppPipAction is false, system-wide PIP is used.
-    private boolean mInAppPipAction = true;
-
     public TvOptionsRowAdapter(Context context, List<CustomAction> customActions) {
         super(context, customActions);
     }
@@ -53,123 +46,73 @@
     protected List<MenuAction> createBaseActions() {
         List<MenuAction> actionList = new ArrayList<>();
         actionList.add(MenuAction.SELECT_CLOSED_CAPTION_ACTION);
-        setOptionChangedListener(MenuAction.SELECT_CLOSED_CAPTION_ACTION);
         actionList.add(MenuAction.SELECT_DISPLAY_MODE_ACTION);
-        setOptionChangedListener(MenuAction.SELECT_DISPLAY_MODE_ACTION);
-        actionList.add(MenuAction.PIP_IN_APP_ACTION);
-        setOptionChangedListener(MenuAction.PIP_IN_APP_ACTION);
-        mPositionPipAction = actionList.size() - 1;
+        if (Features.PICTURE_IN_PICTURE.isEnabled(getMainActivity())) {
+            actionList.add(MenuAction.SYSTEMWIDE_PIP_ACTION);
+        }
         actionList.add(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION);
-        setOptionChangedListener(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION);
         actionList.add(MenuAction.MORE_CHANNELS_ACTION);
-        if (DeveloperOptionFragment.shouldShow()) {
+        if (Utils.isDeveloper()) {
             actionList.add(MenuAction.DEV_ACTION);
         }
         actionList.add(MenuAction.SETTINGS_ACTION);
 
-        if (getCustomActions() != null) {
-            // Adjust Pip action position which will be changed by applying custom actions.
-            for (CustomAction customAction : getCustomActions()) {
-                if (customAction.isFront()) {
-                    mPositionPipAction++;
-                }
-            }
-        }
-
+        updateClosedCaptionAction();
+        updatePipAction();
+        updateMultiAudioAction();
+        updateDisplayModeAction();
         return actionList;
     }
 
     @Override
-    protected boolean updateActions() {
-        boolean changed = false;
+    protected void updateActions() {
+        if (updateClosedCaptionAction()) {
+            notifyItemChanged(getItemPosition(MenuAction.SELECT_CLOSED_CAPTION_ACTION));
+        }
         if (updatePipAction()) {
-            changed = true;
+            notifyItemChanged(getItemPosition(MenuAction.SYSTEMWIDE_PIP_ACTION));
         }
         if (updateMultiAudioAction()) {
-            changed = true;
+            notifyItemChanged(getItemPosition(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION));
         }
         if (updateDisplayModeAction()) {
-            changed = true;
+            notifyItemChanged(getItemPosition(MenuAction.SELECT_DISPLAY_MODE_ACTION));
         }
-        return changed;
-    }
-
-    private boolean updatePipAction() {
-        // There are four states.
-        // Case 1. The device doesn't even have any input for PIP. (e.g. OTT box without HDMI input)
-        //    => Remove the icon.
-        // Case 2. The device has one or more inputs for PIP but none of them are currently
-        // available.
-        //    => Show the icon but disable it.
-        // Case 3. The device has one or more available PIP inputs and now it's tuned off.
-        //    => Show the icon with "Off".
-        // Case 4. The device has one or more available PIP inputs but it's already turned on.
-        //    => Show the icon with "On".
-
-        boolean changed = false;
-
-        // Case 1
-        PipInputManager pipInputManager = getMainActivity().getPipInputManager();
-        if (ENABLE_IN_APP_PIP && pipInputManager.getPipInputSize(false) > 1) {
-            if (!mInAppPipAction) {
-                removeAction(mPositionPipAction);
-                addAction(mPositionPipAction, MenuAction.PIP_IN_APP_ACTION);
-                mInAppPipAction = true;
-                changed = true;
-            }
-        } else {
-            if (mInAppPipAction) {
-                removeAction(mPositionPipAction);
-                mInAppPipAction = false;
-                if (Features.PICTURE_IN_PICTURE.isEnabled(getMainActivity())) {
-                    addAction(mPositionPipAction, MenuAction.SYSTEMWIDE_PIP_ACTION);
-                }
-                return true;
-            }
-            return false;
-        }
-
-        // Case 2
-        boolean isPipEnabled = getMainActivity().isPipEnabled();
-        boolean oldEnabled = MenuAction.PIP_IN_APP_ACTION.isEnabled();
-        boolean newEnabled = pipInputManager.getPipInputSize(true) > 0;
-        if (oldEnabled != newEnabled) {
-            // Should not disable the item if the PIP is already turned on so that the user can
-            // force exit it.
-            if (newEnabled || !isPipEnabled) {
-                MenuAction.PIP_IN_APP_ACTION.setEnabled(newEnabled);
-                changed = true;
-            }
-        }
-
-        // Case 3 & 4 - we just need to update the icon.
-        MenuAction.PIP_IN_APP_ACTION.setDrawableResId(
-                isPipEnabled ? R.drawable.ic_tvoption_pip : R.drawable.ic_tvoption_pip_off);
-        return changed;
     }
 
     @VisibleForTesting
-    boolean updateMultiAudioAction() {
-        List<TvTrackInfo> audioTracks = getMainActivity().getTracks(TvTrackInfo.TYPE_AUDIO);
-        boolean oldEnabled = MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled();
-        boolean newEnabled = audioTracks != null && audioTracks.size() > 1;
-        if (oldEnabled != newEnabled) {
-            MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.setEnabled(newEnabled);
-            return true;
+    private boolean updateClosedCaptionAction() {
+        return updateActionDescription(MenuAction.SELECT_CLOSED_CAPTION_ACTION);
+    }
+
+    private boolean updatePipAction() {
+        if (containsItem(MenuAction.SYSTEMWIDE_PIP_ACTION)) {
+            return MenuAction.setEnabled(MenuAction.SYSTEMWIDE_PIP_ACTION,
+                    !getMainActivity().isScreenBlockedByResourceConflictOrParentalControl());
         }
         return false;
     }
 
+    boolean updateMultiAudioAction() {
+        List<TvTrackInfo> audioTracks = getMainActivity().getTracks(TvTrackInfo.TYPE_AUDIO);
+        boolean enabled = audioTracks != null && audioTracks.size() > 1;
+        // Use "|" operator for non-short-circuit evaluation.
+        return MenuAction.setEnabled(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION, enabled)
+                | updateActionDescription(MenuAction.SELECT_AUDIO_LANGUAGE_ACTION);
+    }
+
     private boolean updateDisplayModeAction() {
         TvViewUiManager uiManager = getMainActivity().getTvViewUiManager();
-        boolean oldEnabled = MenuAction.SELECT_DISPLAY_MODE_ACTION.isEnabled();
-        boolean newEnabled = uiManager.isDisplayModeAvailable(DisplayMode.MODE_FULL)
+        boolean enabled = uiManager.isDisplayModeAvailable(DisplayMode.MODE_FULL)
                 || uiManager.isDisplayModeAvailable(DisplayMode.MODE_ZOOM);
-        if (oldEnabled != newEnabled) {
-            MenuAction.SELECT_DISPLAY_MODE_ACTION.setEnabled(newEnabled);
-            return true;
-        }
-        return false;
+        // Use "|" operator for non-short-circuit evaluation.
+        return MenuAction.setEnabled(MenuAction.SELECT_DISPLAY_MODE_ACTION, enabled)
+                | updateActionDescription(MenuAction.SELECT_DISPLAY_MODE_ACTION);
+    }
+
+    private boolean updateActionDescription(MenuAction action) {
+        return MenuAction.setActionDescription(action,
+                getMainActivity().getTvOptionsManager().getOptionString(action.getType()));
     }
 
     @Override
@@ -183,9 +126,6 @@
                 getMainActivity().getOverlayManager().getSideFragmentManager()
                         .show(new DisplayModeFragment());
                 break;
-            case TvOptionsManager.OPTION_IN_APP_PIP:
-                getMainActivity().togglePipView();
-                break;
             case TvOptionsManager.OPTION_SYSTEMWIDE_PIP:
                 getMainActivity().enterPictureInPictureMode();
                 break;
@@ -205,4 +145,4 @@
                 break;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/onboarding/SetupSourcesFragment.java b/src/com/android/tv/onboarding/SetupSourcesFragment.java
index 7607822..f56daec 100644
--- a/src/com/android/tv/onboarding/SetupSourcesFragment.java
+++ b/src/com/android/tv/onboarding/SetupSourcesFragment.java
@@ -38,6 +38,7 @@
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.TvInputNewComparator;
+import com.android.tv.tuner.TunerInputController;
 import com.android.tv.ui.GuidedActionsStylistWithDivider;
 import com.android.tv.util.SetupUtils;
 import com.android.tv.util.TvInputManagerHelper;
@@ -204,6 +205,7 @@
             mChannelDataManager.addListener(mChannelDataManagerListener);
             super.onCreate(savedInstanceState);
             mParentFragment = (SetupSourcesFragment) getParentFragment();
+            TunerInputController.executeNetworkTunerDiscoveryAsyncTask(getContext());
         }
 
         @Override
diff --git a/src/com/android/tv/parental/ContentRatingSystem.java b/src/com/android/tv/parental/ContentRatingSystem.java
index 6b5d663..5672b79 100644
--- a/src/com/android/tv/parental/ContentRatingSystem.java
+++ b/src/com/android/tv/parental/ContentRatingSystem.java
@@ -110,6 +110,15 @@
         return mRatings;
     }
 
+    public Rating getRating(String name) {
+        for (Rating rating : mRatings) {
+            if (TextUtils.equals(rating.getName(), name)) {
+                return rating;
+            }
+        }
+        return null;
+    }
+
     public List<SubRating> getSubRatings(){
         return mSubRatings;
     }
diff --git a/src/com/android/tv/parental/ContentRatingsManager.java b/src/com/android/tv/parental/ContentRatingsManager.java
index 57c25f4..c3bb8c0 100644
--- a/src/com/android/tv/parental/ContentRatingsManager.java
+++ b/src/com/android/tv/parental/ContentRatingsManager.java
@@ -20,7 +20,10 @@
 import android.media.tv.TvContentRating;
 import android.media.tv.TvContentRatingSystemInfo;
 import android.media.tv.TvInputManager;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
 
+import com.android.tv.R;
 import com.android.tv.parental.ContentRatingSystem.Rating;
 import com.android.tv.parental.ContentRatingSystem.SubRating;
 
@@ -53,6 +56,19 @@
     }
 
     /**
+     * Returns the content rating system with the give ID.
+     */
+    @Nullable
+    public ContentRatingSystem getContentRatingSystem(String contentRatingSystemId) {
+        for (ContentRatingSystem ratingSystem : mContentRatingSystems) {
+            if (TextUtils.equals(ratingSystem.getId(), contentRatingSystemId)) {
+                return ratingSystem;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Returns a new list of all content rating systems defined.
      */
     public List<ContentRatingSystem> getContentRatingSystems() {
@@ -64,6 +80,9 @@
      * displayed to the user. For example, "TV-PG (L, S)".
      */
     public String getDisplayNameForRating(TvContentRating canonicalRating) {
+        if (TvContentRating.UNRATED.equals(canonicalRating)) {
+            return mContext.getResources().getString(R.string.unrated_rating_name);
+        }
         Rating rating = getRating(canonicalRating);
         if (rating == null) {
             return null;
diff --git a/src/com/android/tv/parental/ParentalControlSettings.java b/src/com/android/tv/parental/ParentalControlSettings.java
index d7e1846..2471c56 100644
--- a/src/com/android/tv/parental/ParentalControlSettings.java
+++ b/src/com/android/tv/parental/ParentalControlSettings.java
@@ -20,6 +20,7 @@
 import android.media.tv.TvContentRating;
 import android.media.tv.TvInputManager;
 
+import com.android.tv.experiments.Experiments;
 import com.android.tv.parental.ContentRatingSystem.Rating;
 import com.android.tv.parental.ContentRatingSystem.SubRating;
 import com.android.tv.util.TvSettings;
@@ -109,6 +110,10 @@
         @ContentRatingLevel int currentLevel = getContentRatingLevel();
         if (currentLevel != TvSettings.CONTENT_RATING_LEVEL_CUSTOM) {
             mRatings = ContentRatingLevelPolicy.getRatingsForLevel(this, manager, currentLevel);
+            if (currentLevel != TvSettings.CONTENT_RATING_LEVEL_NONE) {
+                // UNRATED contents should be blocked unless the rating level is none or custom
+                mRatings.add(TvContentRating.UNRATED);
+            }
             storeRatings();
         }
     }
@@ -129,6 +134,11 @@
             }
         } else {
             mRatings = ContentRatingLevelPolicy.getRatingsForLevel(this, manager, level);
+            if (level != TvSettings.CONTENT_RATING_LEVEL_NONE
+                    && Boolean.TRUE.equals(Experiments.ENABLE_UNRATED_CONTENT_SETTINGS.get())) {
+                // UNRATED contents should be blocked unless the rating level is none or custom
+                mRatings.add(TvContentRating.UNRATED);
+            }
         }
         storeRatings();
     }
@@ -138,6 +148,23 @@
         return TvSettings.getContentRatingLevel(mContext);
     }
 
+    /** Sets the blocked status of a unrated contents. */
+    public boolean setUnratedBlocked(boolean blocked) {
+        boolean changed;
+        if (blocked) {
+            changed = mRatings.add(TvContentRating.UNRATED);
+            mTvInputManager.addBlockedRating(TvContentRating.UNRATED);
+        } else {
+            changed = mRatings.remove(TvContentRating.UNRATED);
+            mTvInputManager.removeBlockedRating(TvContentRating.UNRATED);
+        }
+        if (changed) {
+            // change to custom level if the blocked status is changed
+            changeToCustomLevel();
+        }
+        return changed;
+    }
+
     /**
      * Sets the blocked status of a given content rating.
      * <p>
@@ -172,8 +199,10 @@
      * @return The {@link TvContentRating} that is blocked.
      */
     public TvContentRating getBlockedRating(TvContentRating[] ratings) {
-        if (ratings == null) {
-            return null;
+        if (ratings == null || ratings.length <= 0) {
+            return mTvInputManager.isRatingBlocked(TvContentRating.UNRATED)
+                    ? TvContentRating.UNRATED
+                    : null;
         }
         for (TvContentRating rating : ratings) {
             if (mTvInputManager.isRatingBlocked(rating)) {
diff --git a/src/com/android/tv/perf/EventNames.java b/src/com/android/tv/perf/EventNames.java
new file mode 100644
index 0000000..6026897
--- /dev/null
+++ b/src/com/android/tv/perf/EventNames.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2017 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.perf;
+
+import android.support.annotation.StringDef;
+
+import java.lang.annotation.Retention;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Constants for performance event names.
+ *
+ * <p>Only constants are used to insure no PII is sent.
+ *
+ */
+public final class EventNames {
+
+    @Retention(SOURCE)
+    @StringDef({
+        APPLICATION_ONCREATE,
+        FETCH_EPG_TASK,
+        MAIN_ACTIVITY_ONCREATE,
+        MAIN_ACTIVITY_ONSTART,
+        MAIN_ACTIVITY_ONRESUME,
+        ON_DEVICE_SEARCH
+    })
+    public @interface EventName {}
+
+    public static final String APPLICATION_ONCREATE = "Application.onCreate";
+    public static final String FETCH_EPG_TASK = "FetchEpgTask";
+    public static final String MAIN_ACTIVITY_ONCREATE = "MainActivity.onCreate";
+    public static final String MAIN_ACTIVITY_ONSTART = "MainActivity.onStart";
+    public static final String MAIN_ACTIVITY_ONRESUME = "MainActivity.onResume";
+    /**
+     * Event name for query running time of on-device search in
+     * {@link com.android.tv.search.LocalSearchProvider}.
+     */
+    public static final String ON_DEVICE_SEARCH = "OnDeviceSearch";
+
+    private EventNames() {}
+}
diff --git a/src/com/android/tv/perf/PerformanceMonitor.java b/src/com/android/tv/perf/PerformanceMonitor.java
new file mode 100644
index 0000000..40368b4
--- /dev/null
+++ b/src/com/android/tv/perf/PerformanceMonitor.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2017 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.perf;
+
+import android.content.Context;
+
+import static com.android.tv.perf.EventNames.EventName;
+
+/** Measures Performance. */
+public interface PerformanceMonitor {
+
+    /**
+     * Starts monitoring application's lifecylce for interesting memory events, captures and records
+     * memory usage data whenever these events are fired.
+     */
+    void startMemoryMonitor();
+
+    /**
+     * Collects and records memory usage for a specific custom event
+     *
+     * @param eventName to record
+     */
+    void recordMemory(@EventName String eventName);
+
+    /**
+     * Starts a timer for a global event to allow measuring the event's latency across activities If
+     * multiple events with the same name are started, only the last event is retained.
+     *
+     * @param eventName for which the timer starts
+     */
+    void startGlobalTimer(@EventName String eventName);
+
+    /**
+     * Stops a cross activities timer for a specific eventName and records the timer duration. If no
+     * timer found for the event specified an error will be logged, and recording will be skipped.
+     *
+     * @param eventName for which the timer stops
+     */
+    void stopGlobalTimer(@EventName String eventName);
+
+    /**
+     * Starts a timer to record latency of a specific scenario or event. Use this method to track
+     * latency in the same method/class
+     *
+     * @return TimerEvent object to be used for stopping/recording the timer for a specific event.
+     *     If PerformanceMonitor is not initialized for any reason, an empty TimerEvent will be
+     *     returned.
+     */
+    TimerEvent startTimer();
+
+
+    /**
+     * Stops timer for a specific event and records the timer duration. passing a null TimerEvent
+     * will cause this operation to be skipped.
+     *
+     * @param event that needs to be stopped
+     * @param eventName for which the timer stops. This must be constant with no PII.
+     */
+    void stopTimer(TimerEvent event, @EventName String eventName);
+
+    /**
+     * Starts recording jank for a specific scenario or event.
+     *
+     * <p>If jank recording was started already for an event with the current name, but was never
+     * stopped, the previously recorded event will be skipped.
+     *
+     * @param eventName of the event for which tracking is started
+     */
+    void startJankRecorder(@EventName String eventName);
+
+    /**
+     * Stops recording jank for a specific event and records the jank event.
+     *
+     * @param eventName of the event that needs to be stopped
+     */
+    void stopJankRecorder(@EventName String eventName);
+
+    /**
+     * Starts activity to display PerformanceMonitor events recorded in local database for debug
+     * purpose.
+     *
+     * @return true if the activity is available to start
+     */
+    boolean startPerformanceMonitorEventDebugActivity(Context context);
+}
diff --git a/src/com/android/tv/perf/StubPerformanceMonitor.java b/src/com/android/tv/perf/StubPerformanceMonitor.java
new file mode 100644
index 0000000..3742a2a
--- /dev/null
+++ b/src/com/android/tv/perf/StubPerformanceMonitor.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 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.perf;
+
+import android.app.Application;
+import android.content.Context;
+
+/** Do nothing implementation of {@link PerformanceMonitor}. */
+public final class StubPerformanceMonitor implements PerformanceMonitor {
+
+    private static final TimerEvent TIMER_EVENT = new TimerEvent() {};
+
+    public static PerformanceMonitor initialize(Application app) {
+        return new StubPerformanceMonitor();
+    }
+
+    @Override
+    public void startMemoryMonitor() {}
+
+    @Override
+    public void recordMemory(String customEventName) {}
+
+    @Override
+    public void startGlobalTimer(String customEventName) {}
+
+    @Override
+    public void stopGlobalTimer(String customEventName) {}
+
+    @Override
+    public TimerEvent startTimer() {
+        return TIMER_EVENT;
+    }
+
+    @Override
+    public void stopTimer(TimerEvent event, String name) {}
+
+    @Override
+    public void startJankRecorder(String eventName) {}
+
+    @Override
+    public void stopJankRecorder(String eventName) {}
+
+    @Override
+    public boolean startPerformanceMonitorEventDebugActivity(Context context) {
+        return false;
+    }
+
+    public static TimerEvent startBootstrapTimer() {
+        return new TimerEvent() {};
+    }
+}
diff --git a/src/com/android/tv/dvr/ui/FullScheduleCardHolder.java b/src/com/android/tv/perf/TimerEvent.java
similarity index 60%
copy from src/com/android/tv/dvr/ui/FullScheduleCardHolder.java
copy to src/com/android/tv/perf/TimerEvent.java
index d4d4d8a..f8ac6b2 100644
--- a/src/com/android/tv/dvr/ui/FullScheduleCardHolder.java
+++ b/src/com/android/tv/perf/TimerEvent.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2017 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.
@@ -14,16 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr.ui;
+package com.android.tv.perf;
 
-/**
- * Special object for schedule preview;
- */
-final class FullScheduleCardHolder {
-    /**
-     * Full schedule card holder.
-     */
-    static final FullScheduleCardHolder FULL_SCHEDULE_CARD_HOLDER = new FullScheduleCardHolder();
-
-    private FullScheduleCardHolder() { }
-}
+/** An event to time */
+public interface TimerEvent {}
diff --git a/src/com/android/tv/receiver/BootCompletedReceiver.java b/src/com/android/tv/receiver/BootCompletedReceiver.java
index 8d6c5a1..369e7d5 100644
--- a/src/com/android/tv/receiver/BootCompletedReceiver.java
+++ b/src/com/android/tv/receiver/BootCompletedReceiver.java
@@ -21,13 +21,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.os.Build;
 import android.util.Log;
 
 import com.android.tv.Features;
 import com.android.tv.TvActivity;
 import com.android.tv.TvApplication;
-import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.dvr.DvrRecordingService;
+import com.android.tv.dvr.recorder.DvrRecordingService;
+import com.android.tv.dvr.recorder.RecordingScheduler;
+import com.android.tv.recommendation.ChannelPreviewUpdater;
 import com.android.tv.recommendation.NotificationService;
 import com.android.tv.util.OnboardingUtils;
 import com.android.tv.util.SetupUtils;
@@ -49,12 +51,20 @@
 
     @Override
     public void onReceive(Context context, Intent intent) {
+        if (!TvApplication.getSingletons(context).getTvInputManagerHelper().hasTvInputManager()) {
+            Log.wtf(TAG, "Stopping because device does not have a TvInputManager");
+            return;
+        }
         if (DEBUG) Log.d(TAG, "boot completed " + intent);
         TvApplication.setCurrentRunningProcess(context, true);
-        // Start {@link NotificationService}.
-        Intent notificationIntent = new Intent(context, NotificationService.class);
-        notificationIntent.setAction(NotificationService.ACTION_SHOW_RECOMMENDATION);
-        context.startService(notificationIntent);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            ChannelPreviewUpdater.getInstance(context).updatePreviewDataForChannelsImmediately();
+        } else {
+            Intent notificationIntent = new Intent(context, NotificationService.class);
+            notificationIntent.setAction(NotificationService.ACTION_SHOW_RECOMMENDATION);
+            context.startService(notificationIntent);
+        }
 
         // Grant permission to already set up packages after the system has finished booting.
         SetupUtils.grantEpgPermissionToSetUpPackages(context);
@@ -74,8 +84,9 @@
             }
         }
 
-        if (CommonFeatures.DVR.isEnabled(context)) {
-            DvrRecordingService.startService(context);
+        RecordingScheduler scheduler = TvApplication.getSingletons(context).getRecordingScheduler();
+        if (scheduler != null) {
+            scheduler.updateAndStartServiceIfNeeded();
         }
     }
 }
diff --git a/src/com/android/tv/receiver/GlobalKeyReceiver.java b/src/com/android/tv/receiver/GlobalKeyReceiver.java
index 8cd4fdf..cc8e76c 100644
--- a/src/com/android/tv/receiver/GlobalKeyReceiver.java
+++ b/src/com/android/tv/receiver/GlobalKeyReceiver.java
@@ -19,7 +19,8 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.media.tv.TvContract;
+import android.os.AsyncTask;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.KeyEvent;
 
@@ -31,27 +32,64 @@
 public class GlobalKeyReceiver extends BroadcastReceiver {
     private static final boolean DEBUG = false;
     private static final String TAG = "GlobalKeyReceiver";
+
     private static final String ACTION_GLOBAL_BUTTON = "android.intent.action.GLOBAL_BUTTON";
+    // Settings.Secure.USER_SETUP_COMPLETE is hidden.
+    private static final String SETTINGS_USER_SETUP_COMPLETE = "user_setup_complete";
+
+    private static long sLastEventTime;
+    private static boolean sUserSetupComplete;
 
     @Override
     public void onReceive(Context context, Intent intent) {
+        if (!TvApplication.getSingletons(context).getTvInputManagerHelper().hasTvInputManager()) {
+            Log.wtf(TAG, "Stopping because device does not have a TvInputManager");
+            return;
+        }
         TvApplication.setCurrentRunningProcess(context, true);
+        Context appContext = context.getApplicationContext();
+        if (DEBUG) Log.d(TAG, "onReceive: " + intent);
+        if (sUserSetupComplete) {
+            handleIntent(appContext, intent);
+        } else {
+            new AsyncTask<Void, Void, Boolean>() {
+                @Override
+                protected Boolean doInBackground(Void... params) {
+                    return Settings.Secure.getInt(appContext.getContentResolver(),
+                            SETTINGS_USER_SETUP_COMPLETE, 0) != 0;
+                }
+
+                @Override
+                protected void onPostExecute(Boolean setupComplete) {
+                    if (DEBUG) Log.d(TAG, "Is setup complete: " + setupComplete);
+                    sUserSetupComplete = setupComplete;
+                    if (sUserSetupComplete) {
+                        handleIntent(appContext, intent);
+                    }
+                }
+            }.execute();
+        }
+    }
+
+    private void handleIntent(Context appContext, Intent intent) {
         if (ACTION_GLOBAL_BUTTON.equals(intent.getAction())) {
             KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
-            if (DEBUG) Log.d(TAG, "onReceive: " + event);
+            if (DEBUG) Log.d(TAG, "handleIntent: " + event);
             int keyCode = event.getKeyCode();
             int action = event.getAction();
-            if (action == KeyEvent.ACTION_UP) {
+            long eventTime = event.getEventTime();
+            if (action == KeyEvent.ACTION_UP && sLastEventTime != eventTime) {
+                // Workaround for b/23947504, the same key event may be sent twice, filter it.
+                sLastEventTime = eventTime;
                 switch (keyCode) {
                     case KeyEvent.KEYCODE_GUIDE:
-                        context.startActivity(
-                                new Intent(Intent.ACTION_VIEW, TvContract.Programs.CONTENT_URI));
+                        ((TvApplication) appContext).handleGuideKey();
                         break;
                     case KeyEvent.KEYCODE_TV:
-                        ((TvApplication) context.getApplicationContext()).handleTvKey();
+                        ((TvApplication) appContext).handleTvKey();
                         break;
                     case KeyEvent.KEYCODE_TV_INPUT:
-                        ((TvApplication) context.getApplicationContext()).handleTvInputKey();
+                        ((TvApplication) appContext).handleTvInputKey();
                         break;
                     default:
                         // Do nothing
diff --git a/src/com/android/tv/receiver/PackageIntentsReceiver.java b/src/com/android/tv/receiver/PackageIntentsReceiver.java
index 26d000e..124172f 100644
--- a/src/com/android/tv/receiver/PackageIntentsReceiver.java
+++ b/src/com/android/tv/receiver/PackageIntentsReceiver.java
@@ -19,17 +19,29 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.net.Uri;
+import android.util.Log;
 
 import com.android.tv.TvApplication;
+import com.android.tv.util.Partner;
 
 /**
  * A class for handling the broadcast intents from PackageManager.
  */
 public class PackageIntentsReceiver extends BroadcastReceiver {
+    private static final String TAG = "PackageIntentsReceiver";
 
     @Override
     public void onReceive(Context context, Intent intent) {
+        if (!TvApplication.getSingletons(context).getTvInputManagerHelper().hasTvInputManager()) {
+            Log.wtf(TAG, "Stopping because device does not have a TvInputManager");
+            return;
+        }
         TvApplication.setCurrentRunningProcess(context, true);
         ((TvApplication) context.getApplicationContext()).handleInputCountChanged();
+
+        Uri uri = intent.getData();
+        final String packageName = (uri != null ? uri.getSchemeSpecificPart() : null);
+        Partner.reset(context, packageName);
     }
 }
diff --git a/src/com/android/tv/recommendation/ChannelPreviewUpdater.java b/src/com/android/tv/recommendation/ChannelPreviewUpdater.java
new file mode 100644
index 0000000..2709ebe
--- /dev/null
+++ b/src/com/android/tv/recommendation/ChannelPreviewUpdater.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2017 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.recommendation;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.app.job.JobService;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+import android.support.media.tv.TvContractCompat;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.tv.ApplicationSingletons;
+import com.android.tv.TvApplication;
+import com.android.tv.data.Channel;
+import com.android.tv.data.PreviewDataManager;
+import com.android.tv.data.PreviewProgramContent;
+import com.android.tv.data.Program;
+import com.android.tv.parental.ParentalControlSettings;
+import com.android.tv.util.Utils;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/** Class for updating the preview programs for {@link Channel}. */
+@RequiresApi(Build.VERSION_CODES.O)
+public class ChannelPreviewUpdater {
+    private static final String TAG = "ChannelPreviewUpdater";
+    // STOPSHIP: set it to false.
+    private static final boolean DEBUG = true;
+
+    private static final int UPATE_PREVIEW_PROGRAMS_JOB_ID = 1000001;
+    private static final long ROUTINE_INTERVAL_MS = TimeUnit.MINUTES.toMillis(10);
+    // The left time of a program should meet the threshold so that it could be recommended.
+    private static final long RECOMMENDATION_THRESHOLD_LEFT_TIME_MS =
+            TimeUnit.MINUTES.toMillis(10);
+    private static final int RECOMMENDATION_THRESHOLD_PROGRESS = 90;  // 90%
+    private static final int RECOMMENDATION_COUNT = 6;
+    private static final int MIN_COUNT_TO_ADD_ROW = 4;
+
+    private static ChannelPreviewUpdater sChannelPreviewUpdater;
+
+    /**
+     * Creates and returns the {@link ChannelPreviewUpdater}.
+     */
+    public static ChannelPreviewUpdater getInstance(Context context) {
+        if (sChannelPreviewUpdater == null) {
+            sChannelPreviewUpdater = new ChannelPreviewUpdater(context.getApplicationContext());
+        }
+        return sChannelPreviewUpdater;
+    }
+
+    private final Context mContext;
+    private final Recommender mRecommender;
+    private final PreviewDataManager mPreviewDataManager;
+    private JobService mJobService;
+    private JobParameters mJobParams;
+
+    private final ParentalControlSettings mParentalControlSettings;
+
+    private boolean mNeedUpdateAfterRecommenderReady = false;
+
+    private Recommender.Listener mRecommenderListener = new Recommender.Listener() {
+        @Override
+        public void onRecommenderReady() {
+            if (mNeedUpdateAfterRecommenderReady) {
+                if (DEBUG) Log.d(TAG, "Recommender is ready");
+                updatePreviewDataForChannelsImmediately();
+                mNeedUpdateAfterRecommenderReady = false;
+            }
+        }
+
+        @Override
+        public void onRecommendationChanged() {
+            updatePreviewDataForChannelsImmediately();
+        }
+    };
+
+    private ChannelPreviewUpdater(Context context) {
+        mContext = context;
+        mRecommender = new Recommender(context, mRecommenderListener, true);
+        mRecommender.registerEvaluator(new RandomEvaluator(), 0.1, 0.1);
+        mRecommender.registerEvaluator(new FavoriteChannelEvaluator(), 0.5, 0.5);
+        mRecommender.registerEvaluator(new RoutineWatchEvaluator(), 1.0, 1.0);
+        ApplicationSingletons appSingleton = TvApplication.getSingletons(context);
+        mPreviewDataManager = appSingleton.getPreviewDataManager();
+        mParentalControlSettings = appSingleton.getTvInputManagerHelper()
+                .getParentalControlSettings();
+    }
+
+    /**
+     * Starts the routine service for updating the preview programs.
+     */
+    public void startRoutineService() {
+        JobScheduler jobScheduler =
+                (JobScheduler) mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE);
+        if (jobScheduler.getPendingJob(UPATE_PREVIEW_PROGRAMS_JOB_ID) != null) {
+            if (DEBUG) Log.d(TAG, "UPDATE_PREVIEW_JOB already exists");
+            return;
+        }
+        JobInfo job = new JobInfo.Builder(UPATE_PREVIEW_PROGRAMS_JOB_ID,
+                new ComponentName(mContext, ChannelPreviewUpdateService.class))
+                .setPeriodic(ROUTINE_INTERVAL_MS)
+                .setPersisted(true)
+                .build();
+        if (jobScheduler.schedule(job) < 0) {
+            Log.i(TAG, "JobScheduler failed to schedule the job");
+        }
+    }
+
+    /** Called when {@link ChannelPreviewUpdateService} is started. */
+    void onStartJob(JobService service, JobParameters params) {
+        if (DEBUG) Log.d(TAG, "onStartJob");
+        mJobService = service;
+        mJobParams = params;
+        updatePreviewDataForChannelsImmediately();
+    }
+
+    /**
+     * Updates the preview programs table.
+     */
+    public void updatePreviewDataForChannelsImmediately() {
+        if (!mRecommender.isReady()) {
+            mNeedUpdateAfterRecommenderReady = true;
+            return;
+        }
+
+        if (!mPreviewDataManager.isLoadFinished()) {
+            mPreviewDataManager.addListener(new PreviewDataManager.PreviewDataListener() {
+                @Override
+                public void onPreviewDataLoadFinished() {
+                    mPreviewDataManager.removeListener(this);
+                    updatePreviewDataForChannels();
+                }
+
+                @Override
+                public void onPreviewDataUpdateFinished() { }
+            });
+            return;
+        }
+        updatePreviewDataForChannels();
+    }
+
+    /** Called when {@link ChannelPreviewUpdateService} is stopped. */
+    void onStopJob() {
+        if (DEBUG) Log.d(TAG, "onStopJob");
+        mJobService = null;
+        mJobParams = null;
+    }
+
+    private void updatePreviewDataForChannels() {
+        new AsyncTask<Void, Void, Set<Program>>() {
+            @Override
+            protected Set<Program> doInBackground(Void... params) {
+                Set<Program> programs = new HashSet<>();
+                List<Channel> channels = new ArrayList<>(mRecommender.recommendChannels());
+                for (Channel channel : channels) {
+                    if (channel.isPhysicalTunerChannel()) {
+                        final Program program = Utils.getCurrentProgram(mContext, channel.getId());
+                        if (program != null
+                                && isChannelRecommendationApplicable(channel, program)) {
+                            programs.add(program);
+                            if (programs.size() >= RECOMMENDATION_COUNT) {
+                                break;
+                            }
+                        }
+                    }
+                }
+                return programs;
+            }
+
+            private boolean isChannelRecommendationApplicable(Channel channel, Program program) {
+                final long programDurationMs =
+                        program.getEndTimeUtcMillis() - program.getStartTimeUtcMillis();
+                if (programDurationMs <= 0) {
+                    return false;
+                }
+                if (TextUtils.isEmpty(program.getPosterArtUri())) {
+                    return false;
+                }
+                if (mParentalControlSettings.isParentalControlsEnabled()
+                        && (channel.isLocked()
+                                || mParentalControlSettings.isRatingBlocked(
+                                        program.getContentRatings()))) {
+                    return false;
+                }
+                long programLeftTimsMs = program.getEndTimeUtcMillis() - System.currentTimeMillis();
+                final int programProgress =
+                        (programDurationMs <= 0)
+                                ? -1
+                                : 100 - (int) (programLeftTimsMs * 100 / programDurationMs);
+
+                // We recommend those programs that meet the condition only.
+                return programProgress < RECOMMENDATION_THRESHOLD_PROGRESS
+                        || programLeftTimsMs > RECOMMENDATION_THRESHOLD_LEFT_TIME_MS;
+            }
+
+            @Override
+            protected void onPostExecute(Set<Program> programs) {
+                updatePreviewDataForChannelsInternal(programs);
+            }
+        }.execute();
+    }
+
+    private void updatePreviewDataForChannelsInternal(Set<Program> programs) {
+        long defaultPreviewChannelId = mPreviewDataManager.getPreviewChannelId(
+                PreviewDataManager.TYPE_DEFAULT_PREVIEW_CHANNEL);
+        if (defaultPreviewChannelId == PreviewDataManager.INVALID_PREVIEW_CHANNEL_ID) {
+            // Only create if there is enough programs
+            if (programs.size() > MIN_COUNT_TO_ADD_ROW) {
+                mPreviewDataManager.createDefaultPreviewChannel(
+                        new PreviewDataManager.OnPreviewChannelCreationResultListener() {
+                            @Override
+                            public void onPreviewChannelCreationResult(
+                                    long createdPreviewChannelId) {
+                                if (createdPreviewChannelId
+                                        != PreviewDataManager.INVALID_PREVIEW_CHANNEL_ID) {
+                                    TvContractCompat.requestChannelBrowsable(
+                                            mContext, createdPreviewChannelId);
+                                    updatePreviewProgramsForPreviewChannel(
+                                            createdPreviewChannelId,
+                                            generatePreviewProgramContentsFromPrograms(
+                                                    createdPreviewChannelId, programs));
+                                }
+                            }
+                        });
+            }
+        } else {
+            updatePreviewProgramsForPreviewChannel(defaultPreviewChannelId,
+                    generatePreviewProgramContentsFromPrograms(defaultPreviewChannelId, programs));
+        }
+    }
+
+    private Set<PreviewProgramContent> generatePreviewProgramContentsFromPrograms(
+            long previewChannelId, Set<Program> programs) {
+        Set<PreviewProgramContent> result = new HashSet<>();
+        for (Program program : programs) {
+            PreviewProgramContent previewProgramContent =
+                    PreviewProgramContent.createFromProgram(mContext, previewChannelId, program);
+            if (previewProgramContent != null) {
+                result.add(previewProgramContent);
+            }
+        }
+        return result;
+    }
+
+    private void updatePreviewProgramsForPreviewChannel(long previewChannelId,
+            Set<PreviewProgramContent> previewProgramContents) {
+        PreviewDataManager.PreviewDataListener previewDataListener
+                = new PreviewDataManager.PreviewDataListener() {
+            @Override
+            public void onPreviewDataLoadFinished() { }
+
+            @Override
+            public void onPreviewDataUpdateFinished() {
+                mPreviewDataManager.removeListener(this);
+                if (mJobService != null && mJobParams != null) {
+                    if (DEBUG) Log.d(TAG, "UpdateAsyncTask.onPostExecute with JobService");
+                    mJobService.jobFinished(mJobParams, false);
+                    mJobService = null;
+                    mJobParams = null;
+                } else {
+                    if (DEBUG) Log.d(TAG, "UpdateAsyncTask.onPostExecute without JobService");
+                }
+            }
+        };
+        mPreviewDataManager.updatePreviewProgramsForChannel(
+                previewChannelId, previewProgramContents, previewDataListener);
+    }
+
+    /**
+     * Job to execute the update of preview programs.
+     */
+    public static class ChannelPreviewUpdateService extends JobService {
+        private ChannelPreviewUpdater mChannelPreviewUpdater;
+
+        @Override
+        public void onCreate() {
+            TvApplication.setCurrentRunningProcess(this, true);
+            if (DEBUG) Log.d(TAG, "ChannelPreviewUpdateService.onCreate");
+            mChannelPreviewUpdater = ChannelPreviewUpdater.getInstance(this);
+        }
+
+        @Override
+        public boolean onStartJob(JobParameters params) {
+            mChannelPreviewUpdater.onStartJob(this, params);
+            return true;
+        }
+
+        @Override
+        public boolean onStopJob(JobParameters params) {
+            mChannelPreviewUpdater.onStopJob();
+            return false;
+        }
+
+        @Override
+        public void onDestroy() {
+            if (DEBUG) Log.d(TAG, "ChannelPreviewUpdateService.onDestroy");
+        }
+    }
+}
diff --git a/src/com/android/tv/recommendation/NotificationService.java b/src/com/android/tv/recommendation/NotificationService.java
index 30ec73e..a44eca4 100644
--- a/src/com/android/tv/recommendation/NotificationService.java
+++ b/src/com/android/tv/recommendation/NotificationService.java
@@ -426,6 +426,7 @@
                 : 100 - (int) (programLeftTimsMs * 100 / programDurationMs);
         Intent intent = new Intent(Intent.ACTION_VIEW, channel.getUri());
         intent.putExtra(TUNE_PARAMS_RECOMMENDATION_TYPE, mRecommendationType);
+        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
         final PendingIntent notificationIntent = PendingIntent.getActivity(this, 0, intent, 0);
 
         // This callback will run on the main thread.
@@ -455,11 +456,17 @@
     }
 
     private Bitmap overlayChannelLogo(Bitmap logo, Bitmap background) {
-        Bitmap result = BitmapUtils.scaleBitmap(
+        Bitmap result = BitmapUtils.getScaledMutableBitmap(
                 background, Integer.MAX_VALUE, mCardImageHeight);
         Bitmap scaledLogo = BitmapUtils.scaleBitmap(
                 logo, mChannelLogoMaxWidth, mChannelLogoMaxHeight);
-        Canvas canvas = new Canvas(result);
+        Canvas canvas;
+        try {
+            canvas = new Canvas(result);
+        } catch (Exception e) {
+            Log.w(TAG, "Failed to create Canvas", e);
+            return background;
+        }
         canvas.drawBitmap(result, new Matrix(), null);
         Rect rect = new Rect();
         int startPadding;
diff --git a/src/com/android/tv/recommendation/RecommendationDataManager.java b/src/com/android/tv/recommendation/RecommendationDataManager.java
index 62ccd57..dc148ec 100644
--- a/src/com/android/tv/recommendation/RecommendationDataManager.java
+++ b/src/com/android/tv/recommendation/RecommendationDataManager.java
@@ -41,7 +41,7 @@
 import com.android.tv.data.Program;
 import com.android.tv.data.WatchedHistoryManager;
 import com.android.tv.util.PermissionUtils;
-import com.android.tv.util.TvProviderUriMatcher;
+import com.android.tv.util.TvUriMatcher;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -505,8 +505,8 @@
         @SuppressLint("SwitchIntDef")
         @Override
         public void onChange(final boolean selfChange, final Uri uri) {
-            switch (TvProviderUriMatcher.match(uri)) {
-                case TvProviderUriMatcher.MATCH_WATCHED_PROGRAM_ID:
+            switch (TvUriMatcher.match(uri)) {
+                case TvUriMatcher.MATCH_WATCHED_PROGRAM_ID:
                     if (!mHandler.hasMessages(MSG_UPDATE_WATCH_HISTORY,
                             TvContract.WatchedPrograms.CONTENT_URI)) {
                         mHandler.obtainMessage(MSG_UPDATE_WATCH_HISTORY, uri).sendToTarget();
diff --git a/src/com/android/tv/recommendation/RecordedProgramPreviewUpdater.java b/src/com/android/tv/recommendation/RecordedProgramPreviewUpdater.java
new file mode 100644
index 0000000..ad55afb
--- /dev/null
+++ b/src/com/android/tv/recommendation/RecordedProgramPreviewUpdater.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2017 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.recommendation;
+
+import android.content.Context;
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.tv.ApplicationSingletons;
+import com.android.tv.TvApplication;
+import com.android.tv.data.PreviewDataManager;
+import com.android.tv.data.PreviewProgramContent;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.data.RecordedProgram;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Class to update the preview data for {@link RecordedProgram}
+ */
+@RequiresApi(Build.VERSION_CODES.O)
+public class RecordedProgramPreviewUpdater {
+    private static final String TAG = "RecordedProgramPreviewUpdater";
+    // STOPSHIP: set it to false.
+    private static final boolean DEBUG = true;
+
+    private static final int RECOMMENDATION_COUNT = 6;
+
+    private static RecordedProgramPreviewUpdater sRecordedProgramPreviewUpdater;
+
+    /**
+     * Creates and returns the {@link RecordedProgramPreviewUpdater}.
+     */
+    public static RecordedProgramPreviewUpdater getInstance(Context context) {
+        if (sRecordedProgramPreviewUpdater == null) {
+            sRecordedProgramPreviewUpdater
+                    = new RecordedProgramPreviewUpdater(context.getApplicationContext());
+        }
+        return sRecordedProgramPreviewUpdater;
+    }
+
+    private final Context mContext;
+    private final PreviewDataManager mPreviewDataManager;
+    private final DvrDataManager mDvrDataManager;
+
+    private RecordedProgramPreviewUpdater(Context context) {
+        mContext = context.getApplicationContext();
+        ApplicationSingletons applicationSingletons = TvApplication.getSingletons(mContext);
+        mPreviewDataManager = applicationSingletons.getPreviewDataManager();
+        mDvrDataManager = applicationSingletons.getDvrDataManager();
+        mDvrDataManager.addRecordedProgramListener(new DvrDataManager.RecordedProgramListener() {
+            @Override
+            public void onRecordedProgramsAdded(RecordedProgram... recordedPrograms) {
+                if (DEBUG) Log.d(TAG, "Add new preview recorded programs");
+                updatePreviewDataForRecordedPrograms();
+            }
+
+            @Override
+            public void onRecordedProgramsChanged(RecordedProgram... recordedPrograms) {
+                if (DEBUG) Log.d(TAG, "Update preview recorded programs");
+                updatePreviewDataForRecordedPrograms();
+            }
+
+            @Override
+            public void onRecordedProgramsRemoved(RecordedProgram... recordedPrograms) {
+                if (DEBUG) Log.d(TAG, "Delete preview recorded programs");
+                updatePreviewDataForRecordedPrograms();
+            }
+        });
+    }
+
+    /**
+     * Updates the preview data for recorded programs.
+     */
+    public void updatePreviewDataForRecordedPrograms() {
+        if (!mPreviewDataManager.isLoadFinished()) {
+            mPreviewDataManager.addListener(new PreviewDataManager.PreviewDataListener() {
+                @Override
+                public void onPreviewDataLoadFinished() {
+                    mPreviewDataManager.removeListener(this);
+                    updatePreviewDataForRecordedPrograms();
+                }
+
+                @Override
+                public void onPreviewDataUpdateFinished() { }
+            });
+            return;
+        }
+        if (!mDvrDataManager.isRecordedProgramLoadFinished()) {
+            mDvrDataManager.addRecordedProgramLoadFinishedListener(
+                    new DvrDataManager.OnRecordedProgramLoadFinishedListener() {
+                @Override
+                public void onRecordedProgramLoadFinished() {
+                    mDvrDataManager.removeRecordedProgramLoadFinishedListener(this);
+                    updatePreviewDataForRecordedPrograms();
+                }
+            });
+            return;
+        }
+        updatePreviewDataForRecordedProgramsInternal();
+    }
+
+    private void updatePreviewDataForRecordedProgramsInternal() {
+        Set<RecordedProgram> recordedPrograms = generateRecommendationRecordedPrograms();
+        Long recordedPreviewChannelId = mPreviewDataManager.getPreviewChannelId(
+                PreviewDataManager.TYPE_RECORDED_PROGRAM_PREVIEW_CHANNEL);
+        if (recordedPreviewChannelId == PreviewDataManager.INVALID_PREVIEW_CHANNEL_ID
+                && !recordedPrograms.isEmpty()) {
+            createPreviewChannelForRecordedPrograms();
+        } else {
+            mPreviewDataManager.updatePreviewProgramsForChannel(recordedPreviewChannelId,
+                    generatePreviewProgramContentsFromRecordedPrograms(
+                            recordedPreviewChannelId, recordedPrograms), null);
+        }
+    }
+
+    private void createPreviewChannelForRecordedPrograms() {
+        mPreviewDataManager.createPreviewChannel(
+                PreviewDataManager.TYPE_RECORDED_PROGRAM_PREVIEW_CHANNEL,
+                new PreviewDataManager.OnPreviewChannelCreationResultListener() {
+                    @Override
+                    public void onPreviewChannelCreationResult(long createdPreviewChannelId) {
+                        if (createdPreviewChannelId
+                                != PreviewDataManager.INVALID_PREVIEW_CHANNEL_ID) {
+                            updatePreviewDataForRecordedProgramsInternal();
+                        }
+                    }
+                });
+    }
+
+    private Set<RecordedProgram> generateRecommendationRecordedPrograms() {
+        Set<RecordedProgram> programs = new HashSet<>();
+        ArrayList<RecordedProgram> sortedRecordedPrograms =
+                new ArrayList<>(mDvrDataManager.getRecordedPrograms());
+        Collections.sort(
+                sortedRecordedPrograms, RecordedProgram.START_TIME_THEN_ID_COMPARATOR.reversed());
+        for (RecordedProgram recordedProgram : sortedRecordedPrograms) {
+            if (!TextUtils.isEmpty(recordedProgram.getPosterArtUri())) {
+                programs.add(recordedProgram);
+                if (programs.size() >= RECOMMENDATION_COUNT) {
+                    break;
+                }
+            }
+        }
+        return programs;
+    }
+
+    private Set<PreviewProgramContent> generatePreviewProgramContentsFromRecordedPrograms(
+            long previewChannelId, Set<RecordedProgram> recordedPrograms) {
+        Set<PreviewProgramContent> result = new HashSet<>();
+        for (RecordedProgram recordedProgram : recordedPrograms) {
+            result.add(PreviewProgramContent.createFromRecordedProgram(mContext, previewChannelId,
+                    recordedProgram));
+        }
+        return result;
+    }
+}
diff --git a/src/com/android/tv/search/DataManagerSearch.java b/src/com/android/tv/search/DataManagerSearch.java
index 5f89a21..d90908f 100644
--- a/src/com/android/tv/search/DataManagerSearch.java
+++ b/src/com/android/tv/search/DataManagerSearch.java
@@ -265,9 +265,7 @@
     }
 
     private String buildIntentData(long channelId) {
-        return TvContract.buildChannelUri(channelId).buildUpon()
-                .appendQueryParameter(Utils.PARAM_SOURCE, SOURCE_TV_SEARCH)
-                .build().toString();
+        return TvContract.buildChannelUri(channelId).toString();
     }
 
     private boolean isRatingBlocked(TvContentRating[] ratings) {
diff --git a/src/com/android/tv/search/LocalSearchProvider.java b/src/com/android/tv/search/LocalSearchProvider.java
index 9255a43..ef9336d 100644
--- a/src/com/android/tv/search/LocalSearchProvider.java
+++ b/src/com/android/tv/search/LocalSearchProvider.java
@@ -23,10 +23,19 @@
 import android.database.MatrixCursor;
 import android.net.Uri;
 import android.os.SystemClock;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.tv.TvApplication;
+import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.TvCommonUtils;
+import com.android.tv.perf.EventNames;
+import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.perf.TimerEvent;
 import com.android.tv.util.PermissionUtils;
+import com.android.tv.util.TvUriMatcher;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -36,6 +45,9 @@
     private static final String TAG = "LocalSearchProvider";
     private static final boolean DEBUG = false;
 
+    /** The authority for LocalSearchProvider. */
+    public static final String AUTHORITY = "com.android.tv.search";
+
     public static final int PROGRESS_PERCENTAGE_HIDE = -1;
 
     // TODO: Remove this once added to the SearchManager.
@@ -56,58 +68,93 @@
     };
 
     private static final String EXPECTED_PATH_PREFIX = "/" + SearchManager.SUGGEST_URI_PATH_QUERY;
+    static final String SUGGEST_PARAMETER_ACTION = "action";
     // The launcher passes 10 as a 'limit' parameter by default.
-    private static final int DEFAULT_SEARCH_LIMIT = 10;
+    @VisibleForTesting
+    static final int DEFAULT_SEARCH_LIMIT = 10;
+    @VisibleForTesting
+    static final int DEFAULT_SEARCH_ACTION = SearchInterface.ACTION_TYPE_AMBIGUOUS;
 
     private static final String NO_LIVE_CONTENTS = "0";
     private static final String LIVE_CONTENTS = "1";
 
-    static final String SUGGEST_PARAMETER_ACTION = "action";
-    static final int DEFAULT_SEARCH_ACTION = SearchInterface.ACTION_TYPE_AMBIGUOUS;
+    private PerformanceMonitor mPerformanceMonitor;
+
+    /** Used only for testing */
+    private SearchInterface mSearchInterface;
 
     @Override
     public boolean onCreate() {
+        mPerformanceMonitor = TvApplication.getSingletons(getContext()).getPerformanceMonitor();
         return true;
     }
 
+    @VisibleForTesting
+    void setSearchInterface(SearchInterface searchInterface) {
+        SoftPreconditions.checkState(TvCommonUtils.isRunningInTest());
+        mSearchInterface = searchInterface;
+    }
+
     @Override
-    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder) {
+    public Cursor query(@NonNull Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        if (TvUriMatcher.match(uri) != TvUriMatcher.MATCH_ON_DEVICE_SEARCH) {
+            throw new IllegalArgumentException("Unknown URI: " + uri);
+        }
+        TimerEvent queryTimer = mPerformanceMonitor.startTimer();
         if (DEBUG) {
             Log.d(TAG, "query(" + uri + ", " + Arrays.toString(projection) + ", " + selection + ", "
                     + Arrays.toString(selectionArgs) + ", " + sortOrder + ")");
         }
         long time = SystemClock.elapsedRealtime();
-        SearchInterface search;
-        if (PermissionUtils.hasAccessAllEpg(getContext())) {
-            if (DEBUG) Log.d(TAG, "Performing TV Provider search.");
-            search = new TvProviderSearch(getContext());
-        } else {
-            if (DEBUG) Log.d(TAG, "Performing Data Manager search.");
-            search = new DataManagerSearch(getContext());
+        SearchInterface search = mSearchInterface;
+        if (search == null) {
+            if (PermissionUtils.hasAccessAllEpg(getContext())) {
+                if (DEBUG) Log.d(TAG, "Performing TV Provider search.");
+                search = new TvProviderSearch(getContext());
+            } else {
+                if (DEBUG) Log.d(TAG, "Performing Data Manager search.");
+                search = new DataManagerSearch(getContext());
+            }
         }
         String query = uri.getLastPathSegment();
-        int limit = DEFAULT_SEARCH_LIMIT;
-        int action = DEFAULT_SEARCH_ACTION;
-        try {
-            limit = Integer.parseInt(uri.getQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT));
-            action = Integer.parseInt(uri.getQueryParameter(SUGGEST_PARAMETER_ACTION));
-        } catch (NumberFormatException | UnsupportedOperationException e) {
-            // Ignore the exceptions
+        int limit = getQueryParamater(uri, SearchManager.SUGGEST_PARAMETER_LIMIT,
+                DEFAULT_SEARCH_LIMIT);
+        if (limit <= 0) {
+            limit = DEFAULT_SEARCH_LIMIT;
+        }
+        int action = getQueryParamater(uri, SUGGEST_PARAMETER_ACTION, DEFAULT_SEARCH_ACTION);
+        if (action < SearchInterface.ACTION_TYPE_START
+                || action > SearchInterface.ACTION_TYPE_END) {
+            action = DEFAULT_SEARCH_ACTION;
         }
         List<SearchResult> results = new ArrayList<>();
         if (!TextUtils.isEmpty(query)) {
             results.addAll(search.search(query, limit, action));
         }
         Cursor c = createSuggestionsCursor(results);
-        if (DEBUG) Log.d(TAG, "Elapsed time: " + (SystemClock.elapsedRealtime() - time) + "(msec)");
+        if (DEBUG) {
+            Log.d(TAG, "Elapsed time(count=" + c.getCount() + "): "
+                    + (SystemClock.elapsedRealtime() - time) + "(msec)");
+        }
+        mPerformanceMonitor.stopTimer(queryTimer, EventNames.ON_DEVICE_SEARCH);
         return c;
     }
 
+    private int getQueryParamater(Uri uri, String key, int defaultValue) {
+        try {
+            return Integer.parseInt(uri.getQueryParameter(key));
+        } catch (NumberFormatException | UnsupportedOperationException e) {
+            // Ignore the exceptions
+        }
+        return defaultValue;
+    }
+
     private Cursor createSuggestionsCursor(List<SearchResult> results) {
         MatrixCursor cursor = new MatrixCursor(SEARCHABLE_COLUMNS, results.size());
         List<String> row = new ArrayList<>(SEARCHABLE_COLUMNS.length);
 
+        int index = 0;
         for (SearchResult result : results) {
             row.clear();
             row.add(result.title);
@@ -122,6 +169,7 @@
             row.add(result.duration == 0 ? null : String.valueOf(result.duration));
             row.add(String.valueOf(result.progressPercentage));
             cursor.addRow(row);
+            if (DEBUG) Log.d(TAG, "Result[" + (++index) + "]: " + result);
         }
         return cursor;
     }
@@ -171,9 +219,20 @@
 
         @Override
         public String toString() {
-            return "channelId: " + channelId +
-                    ", channelNumber: " + channelNumber +
-                    ", title: " + title;
+            return "SearchResult{channelId=" + channelId +
+                    ", channelNumber=" + channelNumber +
+                    ", title=" + title +
+                    ", description=" + description +
+                    ", imageUri=" + imageUri +
+                    ", intentAction=" + intentAction +
+                    ", intentData=" + intentData +
+                    ", contentType=" + contentType +
+                    ", isLive=" + isLive +
+                    ", videoWidth=" + videoWidth +
+                    ", videoHeight=" + videoHeight +
+                    ", duration=" + duration +
+                    ", progressPercentage=" + progressPercentage +
+                    "}";
         }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/tv/search/SearchInterface.java b/src/com/android/tv/search/SearchInterface.java
index caa4581..d631972 100644
--- a/src/com/android/tv/search/SearchInterface.java
+++ b/src/com/android/tv/search/SearchInterface.java
@@ -24,11 +24,11 @@
  * Interface for channel and program search.
  */
 public interface SearchInterface {
-    String SOURCE_TV_SEARCH = "TvSearch";
-
+    int ACTION_TYPE_START = 1;
     int ACTION_TYPE_AMBIGUOUS = 1;
     int ACTION_TYPE_SWITCH_CHANNEL = 2;
     int ACTION_TYPE_SWITCH_INPUT = 3;
+    int ACTION_TYPE_END = 3;
 
     /**
      * Search channels, inputs, or programs.
diff --git a/src/com/android/tv/search/TvProviderSearch.java b/src/com/android/tv/search/TvProviderSearch.java
index 2ceec19..e7d8a02 100644
--- a/src/com/android/tv/search/TvProviderSearch.java
+++ b/src/com/android/tv/search/TvProviderSearch.java
@@ -402,9 +402,7 @@
     }
 
     private String buildIntentData(long channelId) {
-        return TvContract.buildChannelUri(channelId).buildUpon()
-                .appendQueryParameter(Utils.PARAM_SOURCE, SOURCE_TV_SEARCH)
-                .build().toString();
+        return TvContract.buildChannelUri(channelId).toString();
     }
 
     private boolean isRatingBlocked(String ratings) {
@@ -432,6 +430,9 @@
 
         // Find exact matches first.
         for (TvInputInfo input : inputList) {
+            if (input.getType() == TvInputInfo.TYPE_TUNER) {
+                continue;
+            }
             String label = canonicalizeLabel(input.loadLabel(mContext));
             String customLabel = canonicalizeLabel(input.loadCustomLabel(mContext));
             if (TextUtils.equals(query, label) || TextUtils.equals(query, customLabel)) {
@@ -449,6 +450,9 @@
 
         // Then look for partial matches.
         for (TvInputInfo input : inputList) {
+            if (input.getType() == TvInputInfo.TYPE_TUNER) {
+                continue;
+            }
             String label = canonicalizeLabel(input.loadLabel(mContext));
             String customLabel = canonicalizeLabel(input.loadCustomLabel(mContext));
             if ((label != null && label.contains(query)) ||
diff --git a/src/com/android/tv/tuner/ChannelScanFileParser.java b/src/com/android/tv/tuner/ChannelScanFileParser.java
index 2dd3607..a255de3 100644
--- a/src/com/android/tv/tuner/ChannelScanFileParser.java
+++ b/src/com/android/tv/tuner/ChannelScanFileParser.java
@@ -90,10 +90,6 @@
                 if (tokens.length != 3 && tokens.length != 4) {
                     continue;
                 }
-                if (!tokens[0].equals("A")) {
-                    // Only support ATSC
-                    continue;
-                }
                 scanChannelList.add(ScanChannel.forTuner(Integer.parseInt(tokens[1]), tokens[2],
                         tokens.length == 4 ? Integer.parseInt(tokens[3]) : null));
             }
diff --git a/src/com/android/tv/tuner/UsbTunerHal.java b/src/com/android/tv/tuner/DvbTunerHal.java
similarity index 93%
rename from src/com/android/tv/tuner/UsbTunerHal.java
rename to src/com/android/tv/tuner/DvbTunerHal.java
index 22e35ea..ea97723 100644
--- a/src/com/android/tv/tuner/UsbTunerHal.java
+++ b/src/com/android/tv/tuner/DvbTunerHal.java
@@ -26,9 +26,9 @@
 import java.util.TreeSet;
 
 /**
- * A class to handle a hardware USB tuner device.
+ * A class to handle a hardware Linux DVB API supported tuner device.
  */
-public class UsbTunerHal extends TunerHal {
+public class DvbTunerHal extends TunerHal {
 
     private static final Object sLock = new Object();
     // @GuardedBy("sLock")
@@ -37,7 +37,7 @@
     private final DvbDeviceAccessor mDvbDeviceAccessor;
     private DvbDeviceInfoWrapper mDvbDeviceInfo;
 
-    protected UsbTunerHal(Context context) {
+    protected DvbTunerHal(Context context) {
         super(context);
         mDvbDeviceAccessor = new DvbDeviceAccessor(context);
     }
@@ -55,6 +55,7 @@
                     if (DEBUG) Log.d(TAG, "Available device info: " + deviceInfo);
                     mDvbDeviceInfo = deviceInfo;
                     sUsedDvbDevices.add(deviceInfo);
+                    getDeliverySystemTypeFromDevice();
                     return true;
                 }
             }
@@ -169,6 +170,10 @@
     * Gets the number of USB tuner devices currently present.
     */
     public static int getNumberOfDevices(Context context) {
-        return (new DvbDeviceAccessor(context)).getNumOfDvbDevices();
+        try {
+            return (new DvbDeviceAccessor(context)).getNumOfDvbDevices();
+        } catch (Exception e) {
+            return 0;
+        }
     }
 }
diff --git a/src/com/android/tv/tuner/TunerHal.java b/src/com/android/tv/tuner/TunerHal.java
index de19766..1176cdf 100644
--- a/src/com/android/tv/tuner/TunerHal.java
+++ b/src/com/android/tv/tuner/TunerHal.java
@@ -19,7 +19,12 @@
 import android.content.Context;
 import android.support.annotation.IntDef;
 import android.support.annotation.StringDef;
+import android.support.annotation.WorkerThread;
 import android.util.Log;
+import android.util.Pair;
+
+import com.android.tv.Features;
+import com.android.tv.customization.TvCustomizationManager;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -46,14 +51,43 @@
     public static final String MODULATION_8VSB = "8VSB";
     public static final String MODULATION_QAM256 = "QAM256";
 
+    @IntDef({ DELIVERY_SYSTEM_UNDEFINED, DELIVERY_SYSTEM_ATSC, DELIVERY_SYSTEM_DVBC,
+            DELIVERY_SYSTEM_DVBS, DELIVERY_SYSTEM_DVBS2, DELIVERY_SYSTEM_DVBT,
+            DELIVERY_SYSTEM_DVBT2 })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DeliverySystemType {}
+    public static final int DELIVERY_SYSTEM_UNDEFINED = 0;
+    public static final int DELIVERY_SYSTEM_ATSC = 1;
+    public static final int DELIVERY_SYSTEM_DVBC = 2;
+    public static final int DELIVERY_SYSTEM_DVBS = 3;
+    public static final int DELIVERY_SYSTEM_DVBS2 = 4;
+    public static final int DELIVERY_SYSTEM_DVBT = 5;
+    public static final int DELIVERY_SYSTEM_DVBT2 = 6;
+
+    @IntDef({ TUNER_TYPE_BUILT_IN, TUNER_TYPE_USB, TUNER_TYPE_NETWORK })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TunerType {}
     public static final int TUNER_TYPE_BUILT_IN = 1;
     public static final int TUNER_TYPE_USB = 2;
+    public static final int TUNER_TYPE_NETWORK = 3;
 
     protected static final int PID_PAT = 0;
     protected static final int PID_ATSC_SI_BASE = 0x1ffb;
+    protected static final int PID_DVB_SDT = 0x0011;
+    protected static final int PID_DVB_EIT = 0x0012;
     protected static final int DEFAULT_VSB_TUNE_TIMEOUT_MS = 2000;
     protected static final int DEFAULT_QAM_TUNE_TIMEOUT_MS = 4000; // Some device takes time for
                                                                    // QAM256 tuning.
+    @IntDef({
+            BUILT_IN_TUNER_TYPE_LINUX_DVB
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface BuiltInTunerType {}
+    private static final int BUILT_IN_TUNER_TYPE_LINUX_DVB = 1;
+
+    private static Integer sBuiltInTunerType;
+
+    protected @DeliverySystemType int mDeliverySystemType;
     private boolean mIsStreaming;
     private int mFrequency;
     private String mModulation;
@@ -67,33 +101,62 @@
      * @param context context for creating the TunerHal instance
      * @return the TunerHal instance
      */
+    @WorkerThread
     public synchronized static TunerHal createInstance(Context context) {
         TunerHal tunerHal = null;
-        if (getTunerType(context) == TUNER_TYPE_BUILT_IN) {
+        if (DvbTunerHal.getNumberOfDevices(context) > 0) {
+            if (DEBUG) Log.d(TAG, "Use DvbTunerHal");
+            tunerHal = new DvbTunerHal(context);
         }
-        if (tunerHal == null) {
-            tunerHal = new UsbTunerHal(context);
-        }
-        if (tunerHal.openFirstAvailable()) {
-            return tunerHal;
-        }
-        return null;
+        return tunerHal != null && tunerHal.openFirstAvailable() ? tunerHal : null;
     }
 
     /**
      * Gets the number of tuner devices currently present.
      */
-    public static int getTunerCount(Context context) {
-        if (getTunerType(context) == TUNER_TYPE_BUILT_IN) {
+    @WorkerThread
+    public static Pair<Integer, Integer> getTunerTypeAndCount(Context context) {
+        if (useBuiltInTuner(context)) {
+            if (getBuiltInTunerType(context) == BUILT_IN_TUNER_TYPE_LINUX_DVB) {
+                return new Pair<>(TUNER_TYPE_BUILT_IN, DvbTunerHal.getNumberOfDevices(context));
+            }
+        } else {
+            int usbTunerCount = DvbTunerHal.getNumberOfDevices(context);
+            if (usbTunerCount > 0) {
+                return new Pair<>(TUNER_TYPE_USB, usbTunerCount);
+            }
         }
-        return UsbTunerHal.getNumberOfDevices(context);
+        return new Pair<>(null, 0);
     }
 
     /**
-     * Gets the type of tuner devices currently used.
+     * Check a delivery system is for DVB or not.
      */
-    public static int getTunerType(Context context) {
-        return TUNER_TYPE_USB;
+    public static boolean isDvbDeliverySystem(@DeliverySystemType int deliverySystemType) {
+        return deliverySystemType == DELIVERY_SYSTEM_DVBC
+                || deliverySystemType == DELIVERY_SYSTEM_DVBS
+                || deliverySystemType == DELIVERY_SYSTEM_DVBS2
+                || deliverySystemType == DELIVERY_SYSTEM_DVBT
+                || deliverySystemType == DELIVERY_SYSTEM_DVBT2;
+    }
+
+    /**
+     * Returns if tuner input service would use built-in tuners instead of USB tuners or network
+     * tuners.
+     */
+    static boolean useBuiltInTuner(Context context) {
+        return getBuiltInTunerType(context) != 0;
+    }
+
+    private static @BuiltInTunerType int getBuiltInTunerType(Context context) {
+        if (sBuiltInTunerType == null) {
+            sBuiltInTunerType = 0;
+            if (TvCustomizationManager.hasLinuxDvbBuiltInTuner(context)
+                    && DvbTunerHal.getNumberOfDevices(context) > 0) {
+                sBuiltInTunerType = BUILT_IN_TUNER_TYPE_LINUX_DVB;
+            }
+        }
+        return sBuiltInTunerType;
     }
 
     protected TunerHal(Context context) {
@@ -106,6 +169,20 @@
         return mIsStreaming;
     }
 
+    protected void getDeliverySystemTypeFromDevice() {
+        if (mDeliverySystemType == DELIVERY_SYSTEM_UNDEFINED) {
+            mDeliverySystemType = nativeGetDeliverySystemType(getDeviceId());
+        }
+    }
+
+    /**
+     * Returns {@code true} if this tuner HAL can be reused to save tuning time between channels
+     * of the same frequency.
+     */
+    public boolean isReusable() {
+        return true;
+    }
+
     @Override
     protected void finalize() throws Throwable {
         super.finalize();
@@ -131,9 +208,12 @@
      *
      * @param frequency a frequency of the channel to tune to
      * @param modulation a modulation method of the channel to tune to
+     * @param channelNumber channel number when channel number is already known. Some tuner HAL
+     *        may use channelNumber instead of frequency for tune.
      * @return {@code true} if the operation was successful, {@code false} otherwise
      */
-    public synchronized boolean tune(int frequency, @ModulationType String modulation) {
+    public synchronized boolean tune(int frequency, @ModulationType String modulation,
+            String channelNumber) {
         if (!isDeviceOpen()) {
             Log.e(TAG, "There's no available device");
             return false;
@@ -148,6 +228,10 @@
         if (mFrequency == frequency && Objects.equals(mModulation, modulation)) {
             addPidFilter(PID_PAT, FILTER_TYPE_OTHER);
             addPidFilter(PID_ATSC_SI_BASE, FILTER_TYPE_OTHER);
+            if (isDvbDeliverySystem(mDeliverySystemType)) {
+                addPidFilter(PID_DVB_SDT, FILTER_TYPE_OTHER);
+                addPidFilter(PID_DVB_EIT, FILTER_TYPE_OTHER);
+            }
             mIsStreaming = true;
             return true;
         }
@@ -156,6 +240,10 @@
         if (nativeTune(getDeviceId(), frequency, modulation, timeout_ms)) {
             addPidFilter(PID_PAT, FILTER_TYPE_OTHER);
             addPidFilter(PID_ATSC_SI_BASE, FILTER_TYPE_OTHER);
+            if (isDvbDeliverySystem(mDeliverySystemType)) {
+                addPidFilter(PID_DVB_SDT, FILTER_TYPE_OTHER);
+                addPidFilter(PID_DVB_EIT, FILTER_TYPE_OTHER);
+            }
             mFrequency = frequency;
             mModulation = modulation;
             mIsStreaming = true;
@@ -189,6 +277,7 @@
     protected native void nativeAddPidFilter(long deviceId, int pid, @FilterType int filterType);
     protected native void nativeCloseAllPidFilters(long deviceId);
     protected native void nativeSetHasPendingTune(long deviceId, boolean hasPendingTune);
+    protected native int nativeGetDeliverySystemType(long deviceId);
 
     /**
      * Stops current tuning. The tuner device and pid filters will be reset by this call and make
@@ -210,6 +299,10 @@
         nativeSetHasPendingTune(getDeviceId(), hasPendingTune);
     }
 
+    public int getDeliverySystemType() {
+        return mDeliverySystemType;
+    }
+
     protected native void nativeStopTune(long deviceId);
 
     /**
@@ -235,7 +328,7 @@
 
     /**
      * Opens Linux DVB frontend device. This method is called from native JNI and used only for
-     * UsbTunerHal.
+     * DvbTunerHal.
      */
     protected int openDvbFrontEndFd() {
         return -1;
@@ -243,7 +336,7 @@
 
     /**
      * Opens Linux DVB demux device. This method is called from native JNI and used only for
-     * UsbTunerHal.
+     * DvbTunerHal.
      */
     protected int openDvbDemuxFd() {
         return -1;
@@ -251,7 +344,7 @@
 
     /**
      * Opens Linux DVB dvr device. This method is called from native JNI and used only for
-     * UsbTunerHal.
+     * DvbTunerHal.
      */
     protected int openDvbDvrFd() {
         return -1;
diff --git a/src/com/android/tv/tuner/TunerInputController.java b/src/com/android/tv/tuner/TunerInputController.java
index d89b6a0..e06b9b4 100644
--- a/src/com/android/tv/tuner/TunerInputController.java
+++ b/src/com/android/tv/tuner/TunerInputController.java
@@ -16,30 +16,43 @@
 
 package com.android.tv.tuner;
 
+import android.app.AlarmManager;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
 import android.hardware.usb.UsbDevice;
 import android.hardware.usb.UsbManager;
-import android.media.tv.TvInputInfo;
-import android.media.tv.TvInputManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.support.v4.os.BuildCompat;
+import android.os.SystemClock;
+import android.preference.PreferenceManager;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
 import android.util.Log;
 import android.widget.Toast;
 
 import com.android.tv.Features;
+import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.tuner.R;
+import com.android.tv.common.SoftPreconditions;
 import com.android.tv.tuner.setup.TunerSetupActivity;
 import com.android.tv.tuner.tvinput.TunerTvInputService;
+import com.android.tv.tuner.util.SystemPropertiesProxy;
 import com.android.tv.tuner.util.TunerInputInfoUtils;
 
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
 import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Controls the package visibility of {@link TunerTvInputService}.
@@ -48,84 +61,94 @@
  * {@code UsbManager.ACTION_USB_DEVICE_ATTACHED}, and {@code UsbManager.ACTION_USB_DEVICE_ATTACHED}
  * to update the connection status of the supported USB TV tuners.
  */
-public class TunerInputController extends BroadcastReceiver {
+public class TunerInputController {
     private static final boolean DEBUG = true;
     private static final String TAG = "TunerInputController";
+    private static final String PREFERENCE_IS_NETWORK_TUNER_ATTACHED = "network_tuner";
+    private static final String SECURITY_PATCH_LEVEL_KEY = "ro.build.version.security_patch";
+    private static final String SECURITY_PATCH_LEVEL_FORMAT = "yyyy-MM-dd";
+
+    /**
+     * Action of {@link Intent} to check network connection repeatedly when it is necessary.
+     */
+    private static final String CHECKING_NETWORK_CONNECTION =
+            "com.android.tv.action.CHECKING_NETWORK_CONNECTION";
+
+    private static final String EXTRA_CHECKING_DURATION =
+            "com.android.tv.action.extra.CHECKING_DURATION";
+
+    private static final long INITIAL_CHECKING_DURATION_MS = TimeUnit.SECONDS.toMillis(10);
+    private static final long MAXIMUM_CHECKING_DURATION_MS = TimeUnit.MINUTES.toMillis(10);
 
     private static final TunerDevice[] TUNER_DEVICES = {
-        new TunerDevice(0x2040, 0xb123),  // WinTV-HVR-955Q
-        new TunerDevice(0x07ca, 0x0837)   // AverTV Volar Hybrid Q
+        new TunerDevice(0x2040, 0xb123, null), // WinTV-HVR-955Q
+        new TunerDevice(0x07ca, 0x0837, null), // AverTV Volar Hybrid Q
+        // WinTV-dualHD (bulk) will be supported after 2017 April security patch.
+        new TunerDevice(0x2040, 0x826d, "2017-04-01"), // WinTV-dualHD (bulk)
+        // STOPSHIP: Add WinTV-soloHD (Isoc) temporary for test. Remove this after test complete.
+        new TunerDevice(0x2040, 0x0264, null),
     };
 
     private static final int MSG_ENABLE_INPUT_SERVICE = 1000;
     private static final long DVB_DRIVER_CHECK_DELAY_MS = 300;
 
-    private DvbDeviceAccessor mDvbDeviceAccessor;
-    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_ENABLE_INPUT_SERVICE:
-                    Context context = (Context) msg.obj;
-                    if (mDvbDeviceAccessor == null) {
-                        mDvbDeviceAccessor = new DvbDeviceAccessor(context);
-                    }
-                    enableTunerTvInputService(context, mDvbDeviceAccessor.isDvbDeviceAvailable());
-                    break;
-            }
-        }
-    };
-
     /**
-     * Simple data holder for a USB device. Used to represent a tuner model, and compare
-     * against {@link UsbDevice}.
+     * Checks status of USB devices to see if there are available USB tuners connected.
      */
-    private static class TunerDevice {
-        private final int vendorId;
-        private final int productId;
+    public static void onCheckingUsbTunerStatus(Context context, String action) {
+        onCheckingUsbTunerStatus(context, action, new CheckDvbDeviceHandler());
+    }
 
-        private TunerDevice(int vendorId, int productId) {
-            this.vendorId = vendorId;
-            this.productId = productId;
+    private static void onCheckingUsbTunerStatus(Context context, String action,
+            @NonNull CheckDvbDeviceHandler handler) {
+        SharedPreferences sharedPreferences =
+                PreferenceManager.getDefaultSharedPreferences(context);
+        if (TunerHal.useBuiltInTuner(context)) {
+            enableTunerTvInputService(context, true, false, TunerHal.TUNER_TYPE_BUILT_IN);
+            return;
         }
-
-        private boolean equals(UsbDevice device) {
-            return device.getVendorId() == vendorId && device.getProductId() == productId;
+        // Falls back to the below to check USB tuner devices.
+        boolean enabled = isUsbTunerConnected(context);
+        handler.removeMessages(MSG_ENABLE_INPUT_SERVICE);
+        if (enabled) {
+            // Need to check if DVB driver is accessible. Since the driver creation
+            // could be happen after the USB event, delay the checking by
+            // DVB_DRIVER_CHECK_DELAY_MS.
+            handler.sendMessageDelayed(handler.obtainMessage(MSG_ENABLE_INPUT_SERVICE, context),
+                    DVB_DRIVER_CHECK_DELAY_MS);
+        } else {
+            if (sharedPreferences.getBoolean(PREFERENCE_IS_NETWORK_TUNER_ATTACHED, false)) {
+                // Since network tuner is attached, do not disable TunerTvInput,
+                // just updates the TvInputInfo.
+                TunerInputInfoUtils.updateTunerInputInfo(context);
+                return;
+            }
+            enableTunerTvInputService(context, false, false, TextUtils
+                    .equals(action, UsbManager.ACTION_USB_DEVICE_DETACHED) ?
+                    TunerHal.TUNER_TYPE_USB : null);
         }
     }
 
-    @Override
-    public void onReceive(Context context, Intent intent) {
-        if (DEBUG) Log.d(TAG, "Broadcast intent received:" + intent);
-        TvApplication.setCurrentRunningProcess(context, true);
-        if (!Features.TUNER.isEnabled(context)) {
-            enableTunerTvInputService(context, false);
-            return;
-        }
-
-        switch (intent.getAction()) {
-            case Intent.ACTION_BOOT_COMPLETED:
-            case TvApplication.ACTION_APPLICATION_FIRST_LAUNCHED:
-            case UsbManager.ACTION_USB_DEVICE_ATTACHED:
-            case UsbManager.ACTION_USB_DEVICE_DETACHED:
-                if (TunerInputInfoUtils.isBuiltInTuner(context)) {
-                    enableTunerTvInputService(context, true);
-                    break;
-                }
-                // Falls back to the below to check USB tuner devices.
-                boolean enabled = isUsbTunerConnected(context);
-                mHandler.removeMessages(MSG_ENABLE_INPUT_SERVICE);
-                if (enabled) {
-                    // Need to check if DVB driver is accessible. Since the driver creation
-                    // could be happen after the USB event, delay the checking by
-                    // DVB_DRIVER_CHECK_DELAY_MS.
-                    mHandler.sendMessageDelayed(
-                            mHandler.obtainMessage(MSG_ENABLE_INPUT_SERVICE, context),
-                            DVB_DRIVER_CHECK_DELAY_MS);
-                } else {
-                    enableTunerTvInputService(context, false);
-                }
-                break;
+    private static void onNetworkTunerChanged(Context context, boolean enabled) {
+        SharedPreferences sharedPreferences =
+                PreferenceManager.getDefaultSharedPreferences(context);
+        if (enabled) {
+            // Network tuner detection is initiated by UI. So the app should not
+            // be killed.
+            sharedPreferences.edit().putBoolean(PREFERENCE_IS_NETWORK_TUNER_ATTACHED, true).apply();
+            enableTunerTvInputService(context, true, true, TunerHal.TUNER_TYPE_NETWORK);
+        } else {
+            sharedPreferences.edit()
+                    .putBoolean(PREFERENCE_IS_NETWORK_TUNER_ATTACHED, false).apply();
+            if(!isUsbTunerConnected(context) && !TunerHal.useBuiltInTuner(context)) {
+                // Network tuner detection is initiated by UI. So the app should not
+                // be killed.
+                enableTunerTvInputService(context, false, true, TunerHal.TUNER_TYPE_NETWORK);
+            } else {
+                // Since USB tuner is attached, do not disable TunerTvInput,
+                // just updates the TvInputInfo.
+                TunerInputInfoUtils.updateTunerInputInfo(context);
+            }
         }
     }
 
@@ -135,15 +158,18 @@
      * @param context {@link Context} instance
      * @return {@code true} if any tuner device we support is plugged in
      */
-    private boolean isUsbTunerConnected(Context context) {
+    private static boolean isUsbTunerConnected(Context context) {
         UsbManager manager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
         Map<String, UsbDevice> deviceList = manager.getDeviceList();
+        String currentSecurityLevel =
+                SystemPropertiesProxy.getString(SECURITY_PATCH_LEVEL_KEY, null);
+
         for (UsbDevice device : deviceList.values()) {
             if (DEBUG) {
                 Log.d(TAG, "Device: " + device);
             }
             for (TunerDevice tuner : TUNER_DEVICES) {
-                if (tuner.equals(device)) {
+                if (tuner.equals(device) && tuner.isSupported(currentSecurityLevel)) {
                     Log.i(TAG, "Tuner found");
                     return true;
                 }
@@ -158,7 +184,8 @@
      * @param context {@link Context} instance
      * @param enabled {@code true} to enable the service; otherwise {@code false}
      */
-    private void enableTunerTvInputService(Context context, boolean enabled) {
+    private static void enableTunerTvInputService(Context context, boolean enabled,
+            boolean forceDontKillApp, Integer tunerType) {
         if (DEBUG) Log.d(TAG, "enableTunerTvInputService: " + enabled);
         PackageManager pm  = context.getPackageManager();
         ComponentName componentName = new ComponentName(context, TunerTvInputService.class);
@@ -170,23 +197,182 @@
         // Since PackageManager.DONT_KILL_APP delays the operation by 10 seconds
         // (PackageManagerService.BROADCAST_DELAY), we'd better avoid using it. It is used only
         // when the LiveChannels app is active since we don't want to kill the running app.
-        int flags = TvApplication.getSingletons(context).getMainActivityWrapper().isCreated()
+        int flags = forceDontKillApp
+                || TvApplication.getSingletons(context).getMainActivityWrapper().isCreated()
                 ? PackageManager.DONT_KILL_APP : 0;
         int newState = enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
                 : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
         if (newState != pm.getComponentEnabledSetting(componentName)) {
-            // Send/cancel the USB tuner TV input setup recommendation card.
-            TunerSetupActivity.onTvInputEnabled(context, enabled);
+            // Send/cancel the USB tuner TV input setup notification.
+            TunerSetupActivity.onTvInputEnabled(context, enabled, tunerType);
             // Enable/disable the USB tuner TV input.
             pm.setComponentEnabledSetting(componentName, newState, flags);
-            if (!enabled) {
-                Toast.makeText(
-                        context, R.string.msg_usb_device_detached, Toast.LENGTH_SHORT).show();
+            if (!enabled && tunerType != null) {
+                if (tunerType == TunerHal.TUNER_TYPE_USB) {
+                    Toast.makeText(context, R.string.msg_usb_tuner_disconnected,
+                            Toast.LENGTH_SHORT).show();
+                } else if (tunerType == TunerHal.TUNER_TYPE_NETWORK) {
+                    Toast.makeText(context, R.string.msg_network_tuner_disconnected,
+                            Toast.LENGTH_SHORT).show();
+                }
             }
             if (DEBUG) Log.d(TAG, "Status updated:" + enabled);
         } else if (enabled) {
-            // When # of USB tuners is changed or the device just boots.
+            // When # of tuners is changed or the tuner input service is switching from/to using
+            // network tuners or the device just boots.
             TunerInputInfoUtils.updateTunerInputInfo(context);
         }
     }
+
+    /**
+     * Discovers a network tuner. If the network connection is down, it won't repeatedly checking.
+     */
+    public static void executeNetworkTunerDiscoveryAsyncTask(final Context context) {
+        boolean runningInMainProcess =
+                TvApplication.getSingletons(context).isRunningInMainProcess();
+        SoftPreconditions.checkState(runningInMainProcess);
+        if (!runningInMainProcess) {
+            return;
+        }
+        executeNetworkTunerDiscoveryAsyncTask(context, 0);
+    }
+
+    /**
+     * Discovers a network tuner.
+     * @param context {@link Context}
+     * @param repeatedDurationMs the time length to wait to repeatedly check network status to start
+     *                           finding network tuner when the network connection is not available.
+     *                           {@code 0} to disable repeatedly checking.
+     */
+    private static void executeNetworkTunerDiscoveryAsyncTask(final Context context,
+            final long repeatedDurationMs) {
+        if (!Features.NETWORK_TUNER.isEnabled(context)) {
+            return;
+        }
+        new AsyncTask<Void, Void, Boolean>() {
+            @Override
+            protected Boolean doInBackground(Void... params) {
+                if (isNetworkConnected(context)) {
+                    // Implement and execute network tuner discovery AsyncTask here.
+                } else if (repeatedDurationMs > 0) {
+                    AlarmManager alarmManager =
+                            (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+                    Intent networkCheckingIntent = new Intent(context, IntentReceiver.class);
+                    networkCheckingIntent.setAction(CHECKING_NETWORK_CONNECTION);
+                    networkCheckingIntent.putExtra(EXTRA_CHECKING_DURATION, repeatedDurationMs);
+                    PendingIntent alarmIntent = PendingIntent.getBroadcast(
+                            context, 0, networkCheckingIntent, PendingIntent.FLAG_UPDATE_CURRENT);
+                    alarmManager.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime()
+                            + repeatedDurationMs, alarmIntent);
+                }
+                return null;
+            }
+
+            @Override
+            protected void onPostExecute(Boolean result) {
+                if (result == null) {
+                    return;
+                }
+                onNetworkTunerChanged(context, result);
+            }
+        }.execute();
+    }
+
+    private static boolean isNetworkConnected(Context context) {
+        ConnectivityManager cm = (ConnectivityManager)
+                context.getSystemService(Context.CONNECTIVITY_SERVICE);
+        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
+        return networkInfo != null && networkInfo.isConnected();
+    }
+
+    public static class IntentReceiver extends BroadcastReceiver {
+        private final CheckDvbDeviceHandler mHandler = new CheckDvbDeviceHandler();
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG) Log.d(TAG, "Broadcast intent received:" + intent);
+            TvApplication.setCurrentRunningProcess(context, true);
+            if (!Features.TUNER.isEnabled(context)) {
+                enableTunerTvInputService(context, false, false, null);
+                return;
+            }
+            switch (intent.getAction()) {
+                case Intent.ACTION_BOOT_COMPLETED:
+                    executeNetworkTunerDiscoveryAsyncTask(context, INITIAL_CHECKING_DURATION_MS);
+                case TvApplication.ACTION_APPLICATION_FIRST_LAUNCHED:
+                case UsbManager.ACTION_USB_DEVICE_ATTACHED:
+                case UsbManager.ACTION_USB_DEVICE_DETACHED:
+                    onCheckingUsbTunerStatus(context, intent.getAction(), mHandler);
+                    break;
+                case CHECKING_NETWORK_CONNECTION:
+                    long repeatedDurationMs = intent.getLongExtra(EXTRA_CHECKING_DURATION,
+                            INITIAL_CHECKING_DURATION_MS);
+                    executeNetworkTunerDiscoveryAsyncTask(context,
+                            Math.min(repeatedDurationMs * 2, MAXIMUM_CHECKING_DURATION_MS));
+                    break;
+            }
+        }
+    }
+
+    /**
+     * Simple data holder for a USB device. Used to represent a tuner model, and compare
+     * against {@link UsbDevice}.
+     */
+    private static class TunerDevice {
+        private final int vendorId;
+        private final int productId;
+
+        // security patch level from which the specific tuner type is supported.
+        private final String minSecurityLevel;
+
+        private TunerDevice(int vendorId, int productId, String minSecurityLevel) {
+            this.vendorId = vendorId;
+            this.productId = productId;
+            this.minSecurityLevel = minSecurityLevel;
+        }
+
+        private boolean equals(UsbDevice device) {
+            return device.getVendorId() == vendorId && device.getProductId() == productId;
+        }
+
+        private boolean isSupported(String currentSecurityLevel) {
+            if (minSecurityLevel == null) {
+                return true;
+            }
+
+            long supportSecurityLevelTimeStamp = 0;
+            long currentSecurityLevelTimestamp = 0;
+            try {
+                SimpleDateFormat format = new SimpleDateFormat(SECURITY_PATCH_LEVEL_FORMAT);
+                supportSecurityLevelTimeStamp = format.parse(minSecurityLevel).getTime();
+                currentSecurityLevelTimestamp = format.parse(currentSecurityLevel).getTime();
+            } catch (ParseException e) {
+            }
+            return supportSecurityLevelTimeStamp != 0
+                    && supportSecurityLevelTimeStamp <= currentSecurityLevelTimestamp;
+        }
+    }
+
+    private static class CheckDvbDeviceHandler extends Handler {
+        private DvbDeviceAccessor mDvbDeviceAccessor;
+
+        CheckDvbDeviceHandler() {
+            super(Looper.getMainLooper());
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_ENABLE_INPUT_SERVICE:
+                    Context context = (Context) msg.obj;
+                    if (mDvbDeviceAccessor == null) {
+                        mDvbDeviceAccessor = new DvbDeviceAccessor(context);
+                    }
+                    boolean enabled = mDvbDeviceAccessor.isDvbDeviceAvailable();
+                    enableTunerTvInputService(
+                            context, enabled, false, enabled ? TunerHal.TUNER_TYPE_USB : null);
+                    break;
+            }
+        }
+    }
 }
diff --git a/src/com/android/tv/tuner/TunerPreferences.java b/src/com/android/tv/tuner/TunerPreferences.java
index 1547e3a..11a6a96 100644
--- a/src/com/android/tv/tuner/TunerPreferences.java
+++ b/src/com/android/tv/tuner/TunerPreferences.java
@@ -25,11 +25,15 @@
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.Handler;
+import android.support.annotation.GuardedBy;
+import android.support.annotation.IntDef;
 import android.support.annotation.MainThread;
 
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.tuner.TunerPreferenceProvider.Preferences;
 import com.android.tv.tuner.util.TisConfiguration;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 /**
  * A helper class for the USB tuner preferences.
@@ -39,21 +43,53 @@
 
     private static final String PREFS_KEY_CHANNEL_DATA_VERSION = "channel_data_version";
     private static final String PREFS_KEY_SCANNED_CHANNEL_COUNT = "scanned_channel_count";
+    private static final String PREFS_KEY_LAST_POSTAL_CODE = "last_postal_code";
     private static final String PREFS_KEY_SCAN_DONE = "scan_done";
     private static final String PREFS_KEY_LAUNCH_SETUP = "launch_setup";
     private static final String PREFS_KEY_STORE_TS_STREAM = "store_ts_stream";
+    private static final String PREFS_KEY_TRICKPLAY_SETTING = "trickplay_setting";
+    private static final String PREFS_KEY_TRICKPLAY_EXPIRED_MS = "trickplay_expired_ms";
 
     private static final String SHARED_PREFS_NAME = "com.android.tv.tuner.preferences";
 
     public static final int CHANNEL_DATA_VERSION_NOT_SET = -1;
 
+    @IntDef({TRICKPLAY_SETTING_NOT_SET, TRICKPLAY_SETTING_DISABLED, TRICKPLAY_SETTING_ENABLED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TrickplaySetting {
+    }
+
+    /**
+     * Trickplay setting is not changed by a user. Trickplay will be enabled in this case.
+     */
+    public static final int TRICKPLAY_SETTING_NOT_SET = -1;
+
+    /**
+     * Trickplay setting is disabled.
+     */
+    public static final int TRICKPLAY_SETTING_DISABLED = 0;
+
+    /**
+     * Trickplay setting is enabled.
+     */
+    public static final int TRICKPLAY_SETTING_ENABLED = 1;
+
+    @GuardedBy("TunerPreferences.class")
     private static final Bundle sPreferenceValues = new Bundle();
     private static LoadPreferencesTask sLoadPreferencesTask;
     private static ContentObserver sContentObserver;
+    private static TunerPreferencesChangedListener sPreferencesChangedListener = null;
 
     private static boolean sInitialized;
 
     /**
+     * Listeners for TunerPreferences change.
+     */
+    public interface TunerPreferencesChangedListener {
+        void onTunerPreferencesChanged();
+    }
+
+    /**
      * Initializes the USB tuner preferences.
      */
     @MainThread
@@ -86,11 +122,19 @@
     /**
      * Releases the resources.
      */
-    @MainThread
-    public static void release(Context context) {
+    public static synchronized void release(Context context) {
         if (useContentProvider(context) && sContentObserver != null) {
             context.getContentResolver().unregisterContentObserver(sContentObserver);
         }
+        setTunerPreferencesChangedListener(null);
+    }
+
+    /**
+     * Sets the listener for TunerPreferences change.
+     */
+    public static void setTunerPreferencesChangedListener(
+            TunerPreferencesChangedListener listener) {
+        sPreferencesChangedListener = listener;
     }
 
     /**
@@ -99,7 +143,8 @@
      * This preferences is used across processes, so the preferences should be loaded again when the
      * databases changes.
      */
-    public static synchronized void loadPreferences(Context context) {
+    @MainThread
+    public static void loadPreferences(Context context) {
         if (sLoadPreferencesTask != null
                 && sLoadPreferencesTask.getStatus() != AsyncTask.Status.FINISHED) {
             sLoadPreferencesTask.cancel(true);
@@ -113,8 +158,7 @@
         return TisConfiguration.isPackagedWithLiveChannels(context);
     }
 
-    @MainThread
-    public static int getChannelDataVersion(Context context) {
+    public static synchronized int getChannelDataVersion(Context context) {
         SoftPreconditions.checkState(sInitialized);
         if (useContentProvider(context)) {
             return sPreferenceValues.getInt(PREFS_KEY_CHANNEL_DATA_VERSION,
@@ -126,8 +170,7 @@
         }
     }
 
-    @MainThread
-    public static void setChannelDataVersion(Context context, int version) {
+    public static synchronized void setChannelDataVersion(Context context, int version) {
         if (useContentProvider(context)) {
             setPreference(context, PREFS_KEY_CHANNEL_DATA_VERSION, version);
         } else {
@@ -137,8 +180,7 @@
         }
     }
 
-    @MainThread
-    public static int getScannedChannelCount(Context context) {
+    public static synchronized int getScannedChannelCount(Context context) {
         SoftPreconditions.checkState(sInitialized);
         if (useContentProvider(context)) {
             return sPreferenceValues.getInt(PREFS_KEY_SCANNED_CHANNEL_COUNT);
@@ -148,8 +190,7 @@
         }
     }
 
-    @MainThread
-    public static void setScannedChannelCount(Context context, int channelCount) {
+    public static synchronized void setScannedChannelCount(Context context, int channelCount) {
         if (useContentProvider(context)) {
             setPreference(context, PREFS_KEY_SCANNED_CHANNEL_COUNT, channelCount);
         } else {
@@ -159,8 +200,25 @@
         }
     }
 
-    @MainThread
-    public static boolean isScanDone(Context context) {
+    public static synchronized String getLastPostalCode(Context context) {
+        SoftPreconditions.checkState(sInitialized);
+        if (useContentProvider(context)) {
+            return sPreferenceValues.getString(PREFS_KEY_LAST_POSTAL_CODE);
+        } else {
+            return getSharedPreferences(context).getString(PREFS_KEY_LAST_POSTAL_CODE, null);
+        }
+    }
+
+    public static synchronized void setLastPostalCode(Context context, String postalCode) {
+        if (useContentProvider(context)) {
+            setPreference(context, PREFS_KEY_LAST_POSTAL_CODE, postalCode);
+        } else {
+            getSharedPreferences(context).edit()
+                    .putString(PREFS_KEY_LAST_POSTAL_CODE, postalCode).apply();
+        }
+    }
+
+    public static synchronized boolean isScanDone(Context context) {
         SoftPreconditions.checkState(sInitialized);
         if (useContentProvider(context)) {
             return sPreferenceValues.getBoolean(PREFS_KEY_SCAN_DONE);
@@ -170,8 +228,7 @@
         }
     }
 
-    @MainThread
-    public static void setScanDone(Context context) {
+    public static synchronized void setScanDone(Context context) {
         if (useContentProvider(context)) {
             setPreference(context, PREFS_KEY_SCAN_DONE, true);
         } else {
@@ -181,8 +238,7 @@
         }
     }
 
-    @MainThread
-    public static boolean shouldShowSetupActivity(Context context) {
+    public static synchronized boolean shouldShowSetupActivity(Context context) {
         SoftPreconditions.checkState(sInitialized);
         if (useContentProvider(context)) {
             return sPreferenceValues.getBoolean(PREFS_KEY_LAUNCH_SETUP);
@@ -192,8 +248,7 @@
         }
     }
 
-    @MainThread
-    public static void setShouldShowSetupActivity(Context context, boolean need) {
+    public static synchronized void setShouldShowSetupActivity(Context context, boolean need) {
         if (useContentProvider(context)) {
             setPreference(context, PREFS_KEY_LAUNCH_SETUP, need);
         } else {
@@ -203,8 +258,50 @@
         }
     }
 
-    @MainThread
-    public static boolean getStoreTsStream(Context context) {
+    public static synchronized long getTrickplayExpiredMs(Context context) {
+        SoftPreconditions.checkState(sInitialized);
+        if (useContentProvider(context)) {
+            return sPreferenceValues.getLong(PREFS_KEY_TRICKPLAY_EXPIRED_MS, 0);
+        } else {
+            return getSharedPreferences(context)
+                    .getLong(TunerPreferences.PREFS_KEY_TRICKPLAY_EXPIRED_MS, 0);
+        }
+    }
+
+    public static synchronized void setTrickplayExpiredMs(Context context, long timeMs) {
+        if (useContentProvider(context)) {
+            setPreference(context, PREFS_KEY_TRICKPLAY_EXPIRED_MS, timeMs);
+        } else {
+            getSharedPreferences(context).edit()
+                    .putLong(TunerPreferences.PREFS_KEY_TRICKPLAY_EXPIRED_MS, timeMs)
+                    .apply();
+        }
+    }
+
+    public static synchronized  @TrickplaySetting int getTrickplaySetting(Context context) {
+        SoftPreconditions.checkState(sInitialized);
+        if (useContentProvider(context)) {
+            return sPreferenceValues.getInt(PREFS_KEY_TRICKPLAY_SETTING, TRICKPLAY_SETTING_NOT_SET);
+        } else {
+            return getSharedPreferences(context)
+                .getInt(TunerPreferences.PREFS_KEY_TRICKPLAY_SETTING, TRICKPLAY_SETTING_NOT_SET);
+        }
+    }
+
+    public static synchronized void setTrickplaySetting(Context context,
+            @TrickplaySetting int trickplaySetting) {
+        SoftPreconditions.checkState(sInitialized);
+        SoftPreconditions.checkArgument(trickplaySetting != TRICKPLAY_SETTING_NOT_SET);
+        if (useContentProvider(context)) {
+            setPreference(context, PREFS_KEY_TRICKPLAY_SETTING, trickplaySetting);
+        } else {
+            getSharedPreferences(context).edit()
+                .putInt(TunerPreferences.PREFS_KEY_TRICKPLAY_SETTING, trickplaySetting)
+                .apply();
+        }
+    }
+
+    public static synchronized boolean getStoreTsStream(Context context) {
         SoftPreconditions.checkState(sInitialized);
         if (useContentProvider(context)) {
             return sPreferenceValues.getBoolean(PREFS_KEY_STORE_TS_STREAM, false);
@@ -214,8 +311,7 @@
         }
     }
 
-    @MainThread
-    public static void setStoreTsStream(Context context, boolean shouldStore) {
+    public static synchronized void setStoreTsStream(Context context, boolean shouldStore) {
         if (useContentProvider(context)) {
             setPreference(context, PREFS_KEY_STORE_TS_STREAM, shouldStore);
         } else {
@@ -229,8 +325,28 @@
         return context.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE);
     }
 
-    @MainThread
-    private static void setPreference(final Context context, final String key, final String value) {
+    private static synchronized void setPreference(Context context, String key, String value) {
+        sPreferenceValues.putString(key, value);
+        savePreference(context, key, value);
+    }
+
+    private static synchronized void setPreference(Context context, String key, int value) {
+        sPreferenceValues.putInt(key, value);
+        savePreference(context, key, Integer.toString(value));
+    }
+
+    private static synchronized  void setPreference(Context context, String key, long value) {
+        sPreferenceValues.putLong(key, value);
+        savePreference(context, key, Long.toString(value));
+    }
+
+    private static synchronized void setPreference(Context context, String key, boolean value) {
+        sPreferenceValues.putBoolean(key, value);
+        savePreference(context, key, Boolean.toString(value));
+    }
+
+    private static void savePreference(final Context context, final String key,
+            final String value) {
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
@@ -249,18 +365,6 @@
         }.execute();
     }
 
-    @MainThread
-    private static void setPreference(Context context, String key, int value) {
-        sPreferenceValues.putInt(key, value);
-        setPreference(context, key, Integer.toString(value));
-    }
-
-    @MainThread
-    private static void setPreference(Context context, String key, boolean value) {
-        sPreferenceValues.putBoolean(key, value);
-        setPreference(context, key, Boolean.toString(value));
-    }
-
     private static class LoadPreferencesTask extends AsyncTask<Void, Void, Bundle> {
         private final Context mContext;
         private LoadPreferencesTask(Context context) {
@@ -279,8 +383,12 @@
                         String key = cursor.getString(0);
                         String value = cursor.getString(1);
                         switch (key) {
+                            case PREFS_KEY_TRICKPLAY_EXPIRED_MS:
+                                bundle.putLong(key, Long.parseLong(value));
+                                break;
                             case PREFS_KEY_CHANNEL_DATA_VERSION:
                             case PREFS_KEY_SCANNED_CHANNEL_COUNT:
+                            case PREFS_KEY_TRICKPLAY_SETTING:
                                 try {
                                     bundle.putInt(key, Integer.parseInt(value));
                                 } catch (NumberFormatException e) {
@@ -292,6 +400,9 @@
                             case PREFS_KEY_STORE_TS_STREAM:
                                 bundle.putBoolean(key, Boolean.parseBoolean(value));
                                 break;
+                            case PREFS_KEY_LAST_POSTAL_CODE:
+                                bundle.putString(key, value);
+                                break;
                         }
                     }
                 }
@@ -304,7 +415,14 @@
 
         @Override
         protected void onPostExecute(Bundle bundle) {
-            sPreferenceValues.putAll(bundle);
+            synchronized (TunerPreferences.class) {
+                if (bundle != null) {
+                    sPreferenceValues.putAll(bundle);
+                }
+            }
+            if (sPreferencesChangedListener != null) {
+                sPreferencesChangedListener.onTunerPreferencesChanged();
+            }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/tuner/cc/CaptionTrackRenderer.java b/src/com/android/tv/tuner/cc/CaptionTrackRenderer.java
index 3c75caa..24a0f35 100644
--- a/src/com/android/tv/tuner/cc/CaptionTrackRenderer.java
+++ b/src/com/android/tv/tuner/cc/CaptionTrackRenderer.java
@@ -245,6 +245,10 @@
         }
     }
 
+    public void clear() {
+        mHandler.sendEmptyMessage(MSG_CAPTION_CLEAR);
+    }
+
     public void reset() {
         mCurrentWindowLayout = null;
         mIsDelayed = false;
diff --git a/src/com/android/tv/tuner/cc/Cea708Parser.java b/src/com/android/tv/tuner/cc/Cea708Parser.java
index 92ab062..d0f6cf1 100644
--- a/src/com/android/tv/tuner/cc/Cea708Parser.java
+++ b/src/com/android/tv/tuner/cc/Cea708Parser.java
@@ -140,6 +140,7 @@
     private int mCommand = 0;
     private int mListenServiceNumber = 0;
     private boolean mDtvCcPacking = false;
+    private boolean mFirstServiceNumberDiscovered;
 
     // Assign a dummy listener in order to avoid null checks.
     private OnCea708ParserListener mListener = new OnCea708ParserListener() {
@@ -208,6 +209,15 @@
         }
     }
 
+    public void clear() {
+        mDtvCcPacket.clear();
+        mCcPackets.clear();
+        mBuffer.setLength(0);
+        mDiscoveredNumBytes.clear();
+        mCommand = 0;
+        mDtvCcPacking = false;
+    }
+
     public void setListenServiceNumber(int serviceNumber) {
         mListenServiceNumber = serviceNumber;
     }
@@ -332,12 +342,14 @@
                 mDiscoveredNumBytes.put(
                         serviceNumber, blockSize + mDiscoveredNumBytes.get(serviceNumber, 0));
             }
-            if (mLastDiscoveryLaunchedMs + DISCOVERY_PERIOD_MS < SystemClock.elapsedRealtime()) {
+            if (mLastDiscoveryLaunchedMs + DISCOVERY_PERIOD_MS < SystemClock.elapsedRealtime()
+                    || !mFirstServiceNumberDiscovered) {
                 for (int i = 0; i < mDiscoveredNumBytes.size(); ++i) {
                     int discoveredNumBytes = mDiscoveredNumBytes.valueAt(i);
                     if (discoveredNumBytes >= DISCOVERY_NUM_BYTES_THRESHOLD) {
                         int discoveredServiceNumber = mDiscoveredNumBytes.keyAt(i);
                         mListener.discoverServiceNumber(discoveredServiceNumber);
+                        mFirstServiceNumberDiscovered = true;
                     }
                 }
                 mDiscoveredNumBytes.clear();
diff --git a/src/com/android/tv/tuner/data/PsipData.java b/src/com/android/tv/tuner/data/PsipData.java
index aead4be..8f98e67 100644
--- a/src/com/android/tv/tuner/data/PsipData.java
+++ b/src/com/android/tv/tuner/data/PsipData.java
@@ -24,9 +24,10 @@
 import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import com.android.tv.tuner.ts.SectionParser;
 import com.android.tv.tuner.util.ConvertUtils;
-import com.android.tv.tuner.util.StringUtils;
+import com.android.tv.util.StringUtils;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 
@@ -226,6 +227,50 @@
         }
     }
 
+    public static class SdtItem {
+        private final String mServiceName;
+        private final String mServiceProviderName;
+        private final int mServiceType;
+        private final int mServiceId;
+        private final int mOriginalNetWorkId;
+
+        public SdtItem(String serviceName, String serviceProviderName, int serviceType,
+                       int serviceId, int originalNetWorkId) {
+            mServiceName = serviceName;
+            mServiceProviderName = serviceProviderName;
+            mServiceType = serviceType;
+            mServiceId = serviceId;
+            mOriginalNetWorkId = originalNetWorkId;
+        }
+
+        public String getServiceName() {
+            return mServiceName;
+        }
+
+        public String getServiceProviderName() {
+            return mServiceProviderName;
+        }
+
+        public int getServiceType() {
+            return mServiceType;
+        }
+
+        public int getServiceId() {
+            return mServiceId;
+        }
+
+        public int getOriginalNetworkId() {
+            return mOriginalNetWorkId;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("ServiceName: %s ServiceProviderName:%s ServiceType:%d "
+                            + "OriginalNetworkId:%d",
+                    mServiceName, mServiceProviderName, mServiceType, mOriginalNetWorkId);
+        }
+    }
+
     /**
      * A base class for descriptors of Ts packets.
      */
@@ -462,6 +507,92 @@
         }
     }
 
+    public static class ServiceDescriptor extends TsDescriptor {
+        private final int mServiceType;
+        private final String mServiceProviderName;
+        private final String mServiceName;
+
+        public ServiceDescriptor(int serviceType, String serviceProviderName, String serviceName) {
+            mServiceType = serviceType;
+            mServiceProviderName = serviceProviderName;
+            mServiceName = serviceName;
+        }
+
+        @Override
+        public int getTag() {
+            return SectionParser.DVB_DESCRIPTOR_TAG_SERVICE;
+        }
+
+        public int getServiceType() {
+            return mServiceType;
+        }
+
+        public String getServiceProviderName() {
+            return mServiceProviderName;
+        }
+
+        public String getServiceName() {
+            return mServiceName;
+        }
+
+        @Override
+        public String toString() {
+            return String.format(
+                    "Service descriptor, service type: %d, "
+                            + "service provider name: %s, "
+                            + "service name: %s", mServiceType, mServiceProviderName, mServiceName);
+        }
+    }
+
+    public static class ShortEventDescriptor extends TsDescriptor {
+        private final String mLanguage;
+        private final String mEventName;
+        private final String mText;
+
+        public ShortEventDescriptor(String language, String eventName, String text) {
+            mLanguage = language;
+            mEventName = eventName;
+            mText = text;
+        }
+
+        public String getEventName() {
+            return mEventName;
+        }
+
+        @Override
+        public int getTag() {
+            return SectionParser.DVB_DESCRIPTOR_TAG_SHORT_EVENT;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("ShortEvent Descriptor, language:%s, event name: %s, "
+                    + "text:%s", mLanguage, mEventName, mText);
+        }
+    }
+
+    public static class ParentalRatingDescriptor extends TsDescriptor {
+        private final HashMap<String, Integer> mRatings;
+
+        public ParentalRatingDescriptor(HashMap<String, Integer> ratings) {
+            mRatings = ratings;
+        }
+
+        @Override
+        public int getTag() {
+            return SectionParser.DVB_DESCRIPTOR_TAG_PARENTAL_RATING;
+        }
+
+        public HashMap<String, Integer> getRatings() {
+            return mRatings;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("Parental rating descriptor, ratings:" + mRatings);
+        }
+    }
+
     public static class RatingRegion {
         private final int mName;
         private final String mDescription;
diff --git a/src/com/android/tv/tuner/data/TunerChannel.java b/src/com/android/tv/tuner/data/TunerChannel.java
index 89079d7..1cf514c 100644
--- a/src/com/android/tv/tuner/data/TunerChannel.java
+++ b/src/com/android/tv/tuner/data/TunerChannel.java
@@ -24,7 +24,7 @@
 import com.android.tv.tuner.data.nano.Track.AtscAudioTrack;
 import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import com.android.tv.tuner.util.Ints;
-import com.android.tv.tuner.util.StringUtils;
+import com.android.tv.util.StringUtils;
 import com.google.protobuf.nano.MessageNano;
 
 import java.io.IOException;
@@ -40,6 +40,11 @@
 public class TunerChannel implements Comparable<TunerChannel>, PsipData.TvTracksInterface {
     private static final String TAG = "TunerChannel";
 
+    /**
+     * Channel number separator between major number and minor number.
+     */
+    public static final char CHANNEL_NUMBER_SEPARATOR = '-';
+
     // See ATSC Code Points Registry.
     private static final String[] ATSC_SERVICE_TYPE_NAMES = new String[] {
             "ATSC Reserved",
@@ -63,6 +68,7 @@
     // According to ISO13818-1, Mpeg2 StreamType has a range from 0x00 to 0xff.
     public static final int INVALID_STREAMTYPE = -1;
 
+    // @GuardedBy(this) Writing operations and toByteArray will be guarded. b/34197766
     private final TunerChannelProto mProto;
 
     private TunerChannel(PsipData.VctItem channel, int programNumber,
@@ -88,6 +94,10 @@
             }
             mProto.serviceType = channel.getServiceType();
         }
+        initProto(pmtItems, type);
+    }
+
+    private void initProto(List<PsiData.PmtItem> pmtItems, int type) {
         mProto.type = type;
         mProto.channelId = -1L;
         mProto.frequency = INVALID_FREQUENCY;
@@ -129,14 +139,44 @@
         mProto.audioTrackIndex = (audioPids.size() > 0) ? 0 : -1;
     }
 
+    private TunerChannel(int programNumber, int type, PsipData.SdtItem channel,
+            List<PsiData.PmtItem> pmtItems) {
+        mProto = new TunerChannelProto();
+        mProto.tsid = 0;
+        mProto.virtualMajor = 0;
+        mProto.virtualMinor = 0;
+        if (channel == null) {
+            mProto.shortName = "";
+            mProto.programNumber = programNumber;
+        } else {
+            mProto.shortName = channel.getServiceName();
+            mProto.programNumber = channel.getServiceId();
+            mProto.serviceType = channel.getServiceType();
+        }
+        initProto(pmtItems, type);
+    }
+
+    /**
+     * Initialize tuner channel with VCT items and PMT items.
+     */
     public TunerChannel(PsipData.VctItem channel, List<PsiData.PmtItem> pmtItems) {
         this(channel, 0, pmtItems, Channel.TYPE_TUNER);
     }
 
+    /**
+     * Initialize tuner channel with program number and PMT items.
+     */
     public TunerChannel(int programNumber, List<PsiData.PmtItem> pmtItems) {
         this(null, programNumber, pmtItems, Channel.TYPE_TUNER);
     }
 
+    /**
+     * Initialize tuner channel with SDT items and PMT items.
+     */
+    public TunerChannel(PsipData.SdtItem channel, List<PsiData.PmtItem> pmtItems) {
+        this(0, Channel.TYPE_TUNER, channel, pmtItems);
+    }
+
     private TunerChannel(TunerChannelProto tunerChannelProto) {
         mProto = tunerChannelProto;
     }
@@ -145,6 +185,50 @@
         return new TunerChannel(channel, 0, pmtItems, Channel.TYPE_FILE);
     }
 
+    public static TunerChannel forDvbFile(
+            PsipData.SdtItem channel, List<PsiData.PmtItem> pmtItems) {
+        return new TunerChannel(0, Channel.TYPE_FILE, channel, pmtItems);
+    }
+
+    /**
+     * Create a TunerChannel object suitable for network tuners
+     * @param major Channel number major
+     * @param minor Channel number minor
+     * @param programNumber Program number
+     * @param shortName Short name
+     * @param recordingProhibited Recording prohibition info
+     * @param videoFormat Video format. Should be {@code null} or one of the followings:
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_240P},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_360P},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_480I},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_480P},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_576I},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_576P},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_720P},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_1080I},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_1080P},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_2160P},
+     *                    {@link android.media.tv.TvContract.Channels#VIDEO_FORMAT_4320P}
+     * @return a TunerChannel object
+     */
+    public static TunerChannel forNetwork(int major, int minor, int programNumber,
+            String shortName, boolean recordingProhibited, String videoFormat) {
+        TunerChannel tunerChannel = new TunerChannel(
+                null, programNumber, Collections.EMPTY_LIST, Channel.TYPE_NETWORK);
+        tunerChannel.setVirtualMajor(major);
+        tunerChannel.setVirtualMinor(minor);
+        tunerChannel.setShortName(shortName);
+        // Set audio and video pids in order to work around the audio-only channel check.
+        tunerChannel.setAudioPids(new ArrayList<>(Arrays.asList(0)));
+        tunerChannel.selectAudioTrack(0);
+        tunerChannel.setVideoPid(0);
+        tunerChannel.setRecordingProhibited(recordingProhibited);
+        if (videoFormat != null) {
+            tunerChannel.setVideoFormat(videoFormat);
+        }
+        return tunerChannel;
+    }
+
     public String getName() {
         return (!mProto.shortName.isEmpty()) ? mProto.shortName : mProto.longName;
     }
@@ -193,7 +277,7 @@
         return mProto.videoPid;
     }
 
-    public void setVideoPid(int videoPid) {
+    synchronized public void setVideoPid(int videoPid) {
         mProto.videoPid = videoPid;
     }
 
@@ -219,7 +303,7 @@
         return Ints.asList(mProto.audioPids);
     }
 
-    public void setAudioPids(List<Integer> audioPids) {
+    synchronized public void setAudioPids(List<Integer> audioPids) {
         mProto.audioPids = Ints.toArray(audioPids);
     }
 
@@ -227,7 +311,7 @@
         return Ints.asList(mProto.audioStreamTypes);
     }
 
-    public void setAudioStreamTypes(List<Integer> audioStreamTypes) {
+    synchronized public void setAudioStreamTypes(List<Integer> audioStreamTypes) {
         mProto.audioStreamTypes = Ints.toArray(audioStreamTypes);
     }
 
@@ -239,32 +323,32 @@
         return mProto.type;
     }
 
-    public void setFilepath(String filepath) {
-        mProto.filepath = filepath;
+    synchronized public void setFilepath(String filepath) {
+        mProto.filepath = filepath == null ? "" : filepath;
     }
 
     public String getFilepath() {
         return mProto.filepath;
     }
 
-    public void setVirtualMajor(int virtualMajor) {
+    synchronized public void setVirtualMajor(int virtualMajor) {
         mProto.virtualMajor = virtualMajor;
     }
 
-    public void setVirtualMinor(int virtualMinor) {
+    synchronized public void setVirtualMinor(int virtualMinor) {
         mProto.virtualMinor = virtualMinor;
     }
 
-    public void setShortName(String shortName) {
-        mProto.shortName = shortName;
+    synchronized public void setShortName(String shortName) {
+        mProto.shortName = shortName == null ? "" : shortName;
     }
 
-    public void setFrequency(int frequency) {
+    synchronized public void setFrequency(int frequency) {
         mProto.frequency = frequency;
     }
 
-    public void setModulation(String modulation) {
-        mProto.modulation = modulation;
+    synchronized public void setModulation(String modulation) {
+        mProto.modulation = modulation == null ? "" : modulation;
     }
 
     public boolean hasVideo() {
@@ -279,13 +363,18 @@
         return mProto.channelId;
     }
 
-    public void setChannelId(long channelId) {
+    synchronized public void setChannelId(long channelId) {
         mProto.channelId = channelId;
     }
 
     public String getDisplayNumber() {
-        if (mProto.virtualMajor != 0 && mProto.virtualMinor != 0) {
-            return String.format("%d-%d", mProto.virtualMajor, mProto.virtualMinor);
+        return getDisplayNumber(true);
+    }
+
+    public String getDisplayNumber(boolean ignoreZeroMinorNumber) {
+        if (mProto.virtualMajor != 0 && (mProto.virtualMinor != 0 || !ignoreZeroMinorNumber)) {
+            return String.format("%d%c%d", mProto.virtualMajor, CHANNEL_NUMBER_SEPARATOR,
+                    mProto.virtualMinor);
         } else if (mProto.virtualMajor != 0) {
             return Integer.toString(mProto.virtualMajor);
         } else {
@@ -298,7 +387,7 @@
     }
 
     @Override
-    public void setHasCaptionTrack() {
+    synchronized public void setHasCaptionTrack() {
         mProto.hasCaptionTrack = true;
     }
 
@@ -312,7 +401,7 @@
         return Collections.unmodifiableList(Arrays.asList(mProto.audioTracks));
     }
 
-    public void setAudioTracks(List<AtscAudioTrack> audioTracks) {
+    synchronized public void setAudioTracks(List<AtscAudioTrack> audioTracks) {
         mProto.audioTracks = audioTracks.toArray(new AtscAudioTrack[audioTracks.size()]);
     }
 
@@ -321,11 +410,11 @@
         return Collections.unmodifiableList(Arrays.asList(mProto.captionTracks));
     }
 
-    public void setCaptionTracks(List<AtscCaptionTrack> captionTracks) {
+    synchronized public void setCaptionTracks(List<AtscCaptionTrack> captionTracks) {
         mProto.captionTracks = captionTracks.toArray(new AtscCaptionTrack[captionTracks.size()]);
     }
 
-    public void selectAudioTrack(int index) {
+    synchronized public void selectAudioTrack(int index) {
         if (0 <= index && index < mProto.audioPids.length) {
             mProto.audioTrackIndex = index;
         } else {
@@ -333,6 +422,22 @@
         }
     }
 
+    synchronized public void setRecordingProhibited(boolean recordingProhibited) {
+        mProto.recordingProhibited = recordingProhibited;
+    }
+
+    public boolean isRecordingProhibited() {
+        return mProto.recordingProhibited;
+    }
+
+    synchronized public void setVideoFormat(String videoFormat) {
+        mProto.videoFormat = videoFormat == null ? "" : videoFormat;
+    }
+
+    public String getVideoFormat() {
+        return mProto.videoFormat;
+    }
+
     @Override
     public String toString() {
         switch (mProto.type) {
@@ -359,7 +464,10 @@
         if (ret != 0) {
             return ret;
         }
-
+        ret = StringUtils.compare(getName(), channel.getName());
+        if (ret != 0) {
+            return ret;
+        }
         // For FileTsStreamer, file paths should be compared.
         return StringUtils.compare(getFilepath(), channel.getFilepath());
     }
@@ -374,12 +482,19 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(getFrequency(), getProgramNumber(), getFilepath());
+        return Objects.hash(getFrequency(), getProgramNumber(), getName(), getFilepath());
     }
 
     // Serialization
-    public byte[] toByteArray() {
-        return MessageNano.toByteArray(mProto);
+    synchronized public byte[] toByteArray() {
+        try {
+            return MessageNano.toByteArray(mProto);
+        } catch (Exception e) {
+            // Retry toByteArray. b/34197766
+            Log.w(TAG, "TunerChannel or its variables are modified in multiple thread without lock",
+                    e);
+            return MessageNano.toByteArray(mProto);
+        }
     }
 
     public static TunerChannel parseFrom(byte[] data) {
diff --git a/src/com/android/tv/tuner/exoplayer/Cea708TextTrackRenderer.java b/src/com/android/tv/tuner/exoplayer/Cea708TextTrackRenderer.java
index 5e83922..5f53670 100644
--- a/src/com/android/tv/tuner/exoplayer/Cea708TextTrackRenderer.java
+++ b/src/com/android/tv/tuner/exoplayer/Cea708TextTrackRenderer.java
@@ -40,6 +40,7 @@
     private static final boolean DEBUG = false;
 
     public static final int MSG_SERVICE_NUMBER = 1;
+    public static final int MSG_ENABLE_CLOSED_CAPTION = 2;
 
     // According to CEA-708B, the maximum value of closed caption bandwidth is 9600bps.
     private static final int DEFAULT_INPUT_BUFFER_SIZE = 9600 / 8;
@@ -52,11 +53,13 @@
     private long mCurrentPositionUs;
     private long mPresentationTimeUs;
     private int mTrackIndex;
+    private boolean mRenderingDisabled;
     private Cea708Parser mCea708Parser;
     private CcListener mCcListener;
 
     public interface CcListener {
         void emitEvent(CaptionEvent captionEvent);
+        void clearCaption();
         void discoverServiceNumber(int serviceNumber);
     }
 
@@ -204,7 +207,7 @@
             }
             case SampleSource.SAMPLE_READ: {
                 mSampleHolder.data.flip();
-                if (mCea708Parser != null) {
+                if (mCea708Parser != null && !mRenderingDisabled) {
                     mCea708Parser.parseClosedCaption(mSampleHolder.data, mSampleHolder.timeUs);
                 }
                 return true;
@@ -274,10 +277,26 @@
 
     @Override
     public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
-        if (messageType == MSG_SERVICE_NUMBER) {
-            setServiceNumber((int) message);
-        } else {
-            super.handleMessage(messageType, message);
+        switch (messageType) {
+            case MSG_SERVICE_NUMBER:
+                setServiceNumber((int) message);
+                break;
+            case MSG_ENABLE_CLOSED_CAPTION:
+                boolean renderingDisabled = (Boolean) message == false;
+                if (mRenderingDisabled != renderingDisabled) {
+                    mRenderingDisabled = renderingDisabled;
+                    if (mRenderingDisabled) {
+                        if (mCea708Parser != null) {
+                            mCea708Parser.clear();
+                        }
+                        if (mCcListener != null) {
+                            mCcListener.clearCaption();
+                        }
+                    }
+                }
+                break;
+            default:
+                super.handleMessage(messageType, message);
         }
     }
 }
diff --git a/src/com/android/tv/tuner/exoplayer/ExoPlayerExtractorsFactory.java b/src/com/android/tv/tuner/exoplayer/ExoPlayerExtractorsFactory.java
new file mode 100644
index 0000000..0ab6d8c
--- /dev/null
+++ b/src/com/android/tv/tuner/exoplayer/ExoPlayerExtractorsFactory.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 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.tuner.exoplayer;
+
+import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
+import com.google.android.exoplayer2.extractor.Extractor;
+import com.google.android.exoplayer2.extractor.ExtractorsFactory;
+import com.google.android.exoplayer2.extractor.TimestampAdjuster;
+import com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory;
+import com.google.android.exoplayer2.extractor.ts.TsExtractor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Extractor factory, mainly aim at create TsExtractor with FLAG_ALLOW_NON_IDR_KEYFRAMES flags for
+ * H.264 stream
+ */
+public final class ExoPlayerExtractorsFactory implements ExtractorsFactory {
+    @Override
+    public Extractor[] createExtractors() {
+        // Only create TsExtractor since we only target MPEG2TS stream.
+        Extractor[] extractors = {
+                new TsExtractor(new TimestampAdjuster(0), new DefaultTsPayloadReaderFactory(
+                        DefaultTsPayloadReaderFactory.FLAG_ALLOW_NON_IDR_KEYFRAMES), false) };
+        return extractors;
+    }
+}
diff --git a/src/com/android/tv/tuner/exoplayer/ExoPlayerSampleExtractor.java b/src/com/android/tv/tuner/exoplayer/ExoPlayerSampleExtractor.java
index c105e22..0b64840 100644
--- a/src/com/android/tv/tuner/exoplayer/ExoPlayerSampleExtractor.java
+++ b/src/com/android/tv/tuner/exoplayer/ExoPlayerSampleExtractor.java
@@ -23,17 +23,28 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
+import android.util.Pair;
 
-import com.google.android.exoplayer.C;
 import com.google.android.exoplayer.MediaFormat;
 import com.google.android.exoplayer.MediaFormatHolder;
 import com.google.android.exoplayer.SampleHolder;
-import com.google.android.exoplayer.SampleSource;
-import com.google.android.exoplayer.extractor.ExtractorSampleSource;
-import com.google.android.exoplayer.extractor.ExtractorSampleSource.EventListener;
-import com.google.android.exoplayer.upstream.Allocator;
 import com.google.android.exoplayer.upstream.DataSource;
-import com.google.android.exoplayer.upstream.DefaultAllocator;
+import com.google.android.exoplayer2.C;
+import com.google.android.exoplayer2.Format;
+import com.google.android.exoplayer2.FormatHolder;
+import com.google.android.exoplayer2.Timeline;
+import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
+import com.google.android.exoplayer2.source.ExtractorMediaSource;
+import com.google.android.exoplayer2.source.ExtractorMediaSource.EventListener;
+import com.google.android.exoplayer2.source.MediaPeriod;
+import com.google.android.exoplayer2.source.MediaSource;
+import com.google.android.exoplayer2.source.SampleStream;
+import com.google.android.exoplayer2.source.TrackGroupArray;
+import com.google.android.exoplayer2.trackselection.FixedTrackSelection;
+import com.google.android.exoplayer2.trackselection.TrackSelection;
+import com.google.android.exoplayer2.upstream.DataSpec;
+import com.google.android.exoplayer2.upstream.DefaultAllocator;
+import com.android.tv.tuner.exoplayer.audio.MpegTsDefaultAudioTrackRenderer;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
 import com.android.tv.tuner.exoplayer.buffer.RecordingSampleBuffer;
 import com.android.tv.tuner.exoplayer.buffer.SimpleSampleBuffer;
@@ -42,10 +53,11 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * A class that extracts samples from a live broadcast stream while storing the sample on the disk.
@@ -54,11 +66,7 @@
 public class ExoPlayerSampleExtractor implements SampleExtractor {
     private static final String TAG = "ExoPlayerSampleExtracto";
 
-    // Buffer segment size for memory allocator. Copied from demo implementation of ExoPlayer.
-    private static final int BUFFER_SEGMENT_SIZE_IN_BYTES = 64 * 1024;
-    // Buffer segment count for sample source. Copied from demo implementation of ExoPlayer.
-    private static final int BUFFER_SEGMENT_COUNT = 256;
-
+    private static final int INVALID_TRACK_INDEX = -1;
     private final HandlerThread mSourceReaderThread;
     private final long mId;
 
@@ -70,36 +78,69 @@
     private AtomicBoolean mOnCompletionCalled = new AtomicBoolean();
     private IOException mExceptionOnPrepare;
     private List<MediaFormat> mTrackFormats;
+    private int mVideoTrackIndex = INVALID_TRACK_INDEX;
+    private boolean mVideoTrackMet;
+    private long mBaseSamplePts = Long.MIN_VALUE;
     private HashMap<Integer, Long> mLastExtractedPositionUsMap = new HashMap<>();
+    private final List<Pair<Integer, SampleHolder>> mPendingSamples = new LinkedList<>();
     private OnCompletionListener mOnCompletionListener;
     private Handler mOnCompletionListenerHandler;
     private IOException mError;
 
-    public ExoPlayerSampleExtractor(Uri uri, DataSource source, BufferManager bufferManager,
+    public ExoPlayerSampleExtractor(Uri uri, final DataSource source, BufferManager bufferManager,
             PlaybackBufferListener bufferListener, boolean isRecording) {
         // It'll be used as a timeshift file chunk name's prefix.
         mId = System.currentTimeMillis();
-        Allocator allocator = new DefaultAllocator(BUFFER_SEGMENT_SIZE_IN_BYTES);
 
         EventListener eventListener = new EventListener() {
-
             @Override
-            public void onLoadError(int sourceId, IOException e) {
-                mError = e;
+            public void onLoadError(IOException error) {
+                mError = error;
             }
         };
 
         mSourceReaderThread = new HandlerThread("SourceReaderThread");
-        mSourceReaderWorker = new SourceReaderWorker(new ExtractorSampleSource(uri, source,
-                allocator, BUFFER_SEGMENT_COUNT * BUFFER_SEGMENT_SIZE_IN_BYTES,
+        mSourceReaderWorker = new SourceReaderWorker(new ExtractorMediaSource(uri,
+                new com.google.android.exoplayer2.upstream.DataSource.Factory() {
+                    @Override
+                    public com.google.android.exoplayer2.upstream.DataSource createDataSource() {
+                        // Returns an adapter implementation for ExoPlayer V2 DataSource interface.
+                        return new com.google.android.exoplayer2.upstream.DataSource() {
+                            @Override
+                            public long open(DataSpec dataSpec) throws IOException {
+                                return source.open(
+                                        new com.google.android.exoplayer.upstream.DataSpec(
+                                                dataSpec.uri, dataSpec.postBody,
+                                                dataSpec.absoluteStreamPosition, dataSpec.position,
+                                                dataSpec.length, dataSpec.key, dataSpec.flags));
+                            }
+
+                            @Override
+                            public int read(byte[] buffer, int offset, int readLength)
+                                    throws IOException {
+                                return source.read(buffer, offset, readLength);
+                            }
+
+                            @Override
+                            public Uri getUri() {
+                                return null;
+                            }
+
+                            @Override
+                            public void close() throws IOException {
+                                source.close();
+                            }
+                        };
+                    }
+                },
+                new ExoPlayerExtractorsFactory(),
                 // Do not create a handler if we not on a looper. e.g. test.
-                Looper.myLooper() != null ? new Handler() : null,
-                eventListener, 0));
+                Looper.myLooper() != null ? new Handler() : null, eventListener));
         if (isRecording) {
             mSampleBuffer = new RecordingSampleBuffer(bufferManager, bufferListener, false,
                     RecordingSampleBuffer.BUFFER_REASON_RECORDING);
         } else {
-            if (bufferManager == null || bufferManager.isDisabled()) {
+            if (bufferManager == null) {
                 mSampleBuffer = new SimpleSampleBuffer(bufferListener);
             } else {
                 mSampleBuffer = new RecordingSampleBuffer(bufferManager, bufferListener, true,
@@ -114,97 +155,93 @@
         mOnCompletionListenerHandler = handler;
     }
 
-    private class SourceReaderWorker implements Handler.Callback {
+    private class SourceReaderWorker implements Handler.Callback, MediaPeriod.Callback {
         public static final int MSG_PREPARE = 1;
         public static final int MSG_FETCH_SAMPLES = 2;
         public static final int MSG_RELEASE = 3;
         private static final int RETRY_INTERVAL_MS = 50;
 
-        private final SampleSource mSampleSource;
-        private SampleSource.SampleSourceReader mSampleSourceReader;
+        private final MediaSource mSampleSource;
+        private MediaPeriod mMediaPeriod;
+        private SampleStream[] mStreams;
         private boolean[] mTrackMetEos;
         private boolean mMetEos = false;
         private long mCurrentPosition;
+        private DecoderInputBuffer mDecoderInputBuffer;
+        private SampleHolder mSampleHolder;
+        private boolean mPrepareRequested;
 
-        public SourceReaderWorker(SampleSource sampleSource) {
+        public SourceReaderWorker(MediaSource sampleSource) {
             mSampleSource = sampleSource;
+            mSampleSource.prepareSource(null, false, new MediaSource.Listener() {
+                @Override
+                public void onSourceInfoRefreshed(Timeline timeline, Object manifest) {
+                    // Dynamic stream change is not supported yet. b/28169263
+                    // For now, this will cause EOS and playback reset.
+                }
+            });
+            mDecoderInputBuffer = new DecoderInputBuffer(
+                    DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_NORMAL);
+            mSampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
+        }
+
+        MediaFormat convertFormat(Format format) {
+            if (format.sampleMimeType.startsWith("audio/")) {
+                return MediaFormat.createAudioFormat(format.id, format.sampleMimeType,
+                        format.bitrate, format.maxInputSize,
+                        com.google.android.exoplayer.C.UNKNOWN_TIME_US, format.channelCount,
+                        format.sampleRate, format.initializationData, format.language,
+                        format.pcmEncoding);
+            } else if (format.sampleMimeType.startsWith("video/")) {
+                return MediaFormat.createVideoFormat(
+                        format.id, format.sampleMimeType, format.bitrate, format.maxInputSize,
+                        com.google.android.exoplayer.C.UNKNOWN_TIME_US, format.width, format.height,
+                        format.initializationData, format.rotationDegrees,
+                        format.pixelWidthHeightRatio, format.projectionData, format.stereoMode);
+            } else if (format.sampleMimeType.endsWith("/cea-608")
+                    || format.sampleMimeType.startsWith("text/")) {
+                return MediaFormat.createTextFormat(
+                        format.id, format.sampleMimeType, format.bitrate,
+                        com.google.android.exoplayer.C.UNKNOWN_TIME_US, format.language);
+            } else {
+                return MediaFormat.createFormatForMimeType(
+                        format.id, format.sampleMimeType, format.bitrate,
+                        com.google.android.exoplayer.C.UNKNOWN_TIME_US);
+            }
         }
 
         @Override
-        public boolean handleMessage(Message message) {
-            switch (message.what) {
-                case MSG_PREPARE:
-                    mPrepared = prepare();
-                    if (!mPrepared && mExceptionOnPrepare == null) {
-                            mSourceReaderHandler
-                                    .sendEmptyMessageDelayed(MSG_PREPARE, RETRY_INTERVAL_MS);
-                    } else{
-                        mSourceReaderHandler.sendEmptyMessage(MSG_FETCH_SAMPLES);
-                    }
-                    return true;
-                case MSG_FETCH_SAMPLES:
-                    boolean didSomething = false;
-                    SampleHolder sample = new SampleHolder(
-                            SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
-                    ConditionVariable conditionVariable = new ConditionVariable();
-                    int trackCount = mSampleSourceReader.getTrackCount();
-                    for (int i = 0; i < trackCount; ++i) {
-                        if (!mTrackMetEos[i] && SampleSource.NOTHING_READ
-                                != fetchSample(i, sample, conditionVariable)) {
-                            if (mMetEos) {
-                                // If mMetEos was on during fetchSample() due to an error,
-                                // fetching from other tracks is not necessary.
-                                break;
-                            }
-                            didSomething = true;
-                        }
-                    }
-                    if (!mMetEos) {
-                        if (didSomething) {
-                            mSourceReaderHandler.sendEmptyMessage(MSG_FETCH_SAMPLES);
-                        } else {
-                            mSourceReaderHandler.sendEmptyMessageDelayed(MSG_FETCH_SAMPLES,
-                                    RETRY_INTERVAL_MS);
-                        }
-                    } else {
-                        notifyCompletionIfNeeded(false);
-                    }
-                    return true;
-                case MSG_RELEASE:
-                    if (mSampleSourceReader != null) {
-                        if (mPrepared) {
-                            // ExtractorSampleSource expects all the tracks should be disabled
-                            // before releasing.
-                            int count = mSampleSourceReader.getTrackCount();
-                            for (int i = 0; i < count; ++i) {
-                                mSampleSourceReader.disable(i);
-                            }
-                        }
-                        mSampleSourceReader.release();
-                        mSampleSourceReader = null;
-                    }
-                    cleanUp();
-                    mSourceReaderHandler.removeCallbacksAndMessages(null);
-                    return true;
+        public void onPrepared(MediaPeriod mediaPeriod) {
+            if (mMediaPeriod == null) {
+                // This instance is already released while the extractor is preparing.
+                return;
             }
-            return false;
-        }
-
-        private boolean prepare() {
-            if (mSampleSourceReader == null) {
-                mSampleSourceReader = mSampleSource.register();
+            TrackSelection.Factory selectionFactory = new FixedTrackSelection.Factory();
+            TrackGroupArray trackGroupArray = mMediaPeriod.getTrackGroups();
+            TrackSelection[] selections = new TrackSelection[trackGroupArray.length];
+            for (int i = 0; i < selections.length; ++i) {
+                selections[i] = selectionFactory.createTrackSelection(trackGroupArray.get(i), 0);
             }
-            if(!mSampleSourceReader.prepare(0)) {
-                return false;
-            }
+            boolean retain[] = new boolean[trackGroupArray.length];
+            boolean reset[] = new boolean[trackGroupArray.length];
+            mStreams = new SampleStream[trackGroupArray.length];
+            mMediaPeriod.selectTracks(selections, retain, mStreams, reset, 0);
             if (mTrackFormats == null) {
-                int trackCount = mSampleSourceReader.getTrackCount();
+                int trackCount = trackGroupArray.length;
                 mTrackMetEos = new boolean[trackCount];
                 List<MediaFormat> trackFormats = new ArrayList<>();
+                int videoTrackCount = 0;
                 for (int i = 0; i < trackCount; i++) {
-                    trackFormats.add(mSampleSourceReader.getFormat(i));
-                    mSampleSourceReader.enable(i, 0);
-
+                    Format format = trackGroupArray.get(i).getFormat(0);
+                    if (format.sampleMimeType.startsWith("video/")) {
+                        videoTrackCount++;
+                        mVideoTrackIndex = i;
+                    }
+                    trackFormats.add(convertFormat(format));
+                }
+                if (videoTrackCount > 1) {
+                    // Disable dropping samples when there are multiple video tracks.
+                    mVideoTrackIndex = INVALID_TRACK_INDEX;
                 }
                 mTrackFormats = trackFormats;
                 List<String> ids = new ArrayList<>();
@@ -218,63 +255,178 @@
                     // mExceptionOnPrepare will be notified to ExoPlayer, and ExoPlayer will
                     // call release() eventually.
                     mExceptionOnPrepare = e;
-                    return false;
+                    return;
                 }
+                mSourceReaderHandler.sendEmptyMessage(MSG_FETCH_SAMPLES);
+                mPrepared = true;
             }
-            return true;
+        }
+
+        @Override
+        public void onContinueLoadingRequested(MediaPeriod source) {
+            source.continueLoading(mCurrentPosition);
+        }
+
+        @Override
+        public boolean handleMessage(Message message) {
+            switch (message.what) {
+                case MSG_PREPARE:
+                    if (!mPrepareRequested) {
+                        mPrepareRequested = true;
+                        mMediaPeriod = mSampleSource.createPeriod(0,
+                                new DefaultAllocator(true, C.DEFAULT_BUFFER_SEGMENT_SIZE), 0);
+                        mMediaPeriod.prepare(this);
+                        try {
+                            mMediaPeriod.maybeThrowPrepareError();
+                        } catch (IOException e) {
+                            mError = e;
+                        }
+                    }
+                    return true;
+                case MSG_FETCH_SAMPLES:
+                    boolean didSomething = false;
+                    ConditionVariable conditionVariable = new ConditionVariable();
+                    int trackCount = mStreams.length;
+                    for (int i = 0; i < trackCount; ++i) {
+                        if (!mTrackMetEos[i] && C.RESULT_NOTHING_READ
+                                != fetchSample(i, mSampleHolder, conditionVariable)) {
+                            if (mMetEos) {
+                                // If mMetEos was on during fetchSample() due to an error,
+                                // fetching from other tracks is not necessary.
+                                break;
+                            }
+                            didSomething = true;
+                        }
+                    }
+                    mMediaPeriod.continueLoading(mCurrentPosition);
+                    if (!mMetEos) {
+                        if (didSomething) {
+                            mSourceReaderHandler.sendEmptyMessage(MSG_FETCH_SAMPLES);
+                        } else {
+                            mSourceReaderHandler.sendEmptyMessageDelayed(MSG_FETCH_SAMPLES,
+                                    RETRY_INTERVAL_MS);
+                        }
+                    } else {
+                        notifyCompletionIfNeeded(false);
+                    }
+                    return true;
+                case MSG_RELEASE:
+                    if (mMediaPeriod != null) {
+                        mSampleSource.releasePeriod(mMediaPeriod);
+                        mSampleSource.releaseSource();
+                        mMediaPeriod = null;
+                    }
+                    cleanUp();
+                    mSourceReaderHandler.removeCallbacksAndMessages(null);
+                    return true;
+            }
+            return false;
         }
 
         private int fetchSample(int track, SampleHolder sample,
                 ConditionVariable conditionVariable) {
-            mSampleSourceReader.continueBuffering(track, mCurrentPosition);
-
-            MediaFormatHolder formatHolder = new MediaFormatHolder();
-            sample.clearData();
-            int ret = mSampleSourceReader.readData(track, mCurrentPosition, formatHolder, sample);
-            if (ret == SampleSource.SAMPLE_READ) {
-                if (mCurrentPosition < sample.timeUs) {
-                    mCurrentPosition = sample.timeUs;
+            FormatHolder dummyFormatHolder = new FormatHolder();
+            mDecoderInputBuffer.clear();
+            int ret = mStreams[track].readData(dummyFormatHolder, mDecoderInputBuffer);
+            if (ret == C.RESULT_BUFFER_READ
+                    // Double-check if the extractor provided the data to prevent NPE. b/33758354
+                    && mDecoderInputBuffer.data != null) {
+                if (mCurrentPosition < mDecoderInputBuffer.timeUs) {
+                    mCurrentPosition = mDecoderInputBuffer.timeUs;
                 }
                 try {
                     Long lastExtractedPositionUs = mLastExtractedPositionUsMap.get(track);
                     if (lastExtractedPositionUs == null) {
-                        mLastExtractedPositionUsMap.put(track, sample.timeUs);
+                        mLastExtractedPositionUsMap.put(track, mDecoderInputBuffer.timeUs);
                     } else {
                         mLastExtractedPositionUsMap.put(track,
-                                Math.max(lastExtractedPositionUs, sample.timeUs));
+                                Math.max(lastExtractedPositionUs, mDecoderInputBuffer.timeUs));
                     }
-                    queueSample(track, sample, conditionVariable);
+                    queueSample(track, conditionVariable);
                 } catch (IOException e) {
                     mLastExtractedPositionUsMap.clear();
                     mMetEos = true;
                     mSampleBuffer.setEos();
                 }
-            } else if (ret == SampleSource.END_OF_STREAM) {
+            } else if (ret == C.RESULT_END_OF_INPUT) {
                 mTrackMetEos[track] = true;
                 for (int i = 0; i < mTrackMetEos.length; ++i) {
                     if (!mTrackMetEos[i]) {
                         break;
                     }
-                    if (i == mTrackMetEos.length -1) {
+                    if (i == mTrackMetEos.length - 1) {
                         mMetEos = true;
                         mSampleBuffer.setEos();
                     }
                 }
             }
-            // TODO: Handle SampleSource.FORMAT_READ for dynamic resolution change. b/28169263
+            // TODO: Handle C.RESULT_FORMAT_READ for dynamic resolution change. b/28169263
             return ret;
         }
-    }
 
-    private void queueSample(int index, SampleHolder sample, ConditionVariable conditionVariable)
-            throws IOException {
-        long writeStartTimeNs = SystemClock.elapsedRealtimeNanos();
-        mSampleBuffer.writeSample(index, sample, conditionVariable);
+        private void queueSample(int index, ConditionVariable conditionVariable)
+                throws IOException {
+            if (mVideoTrackIndex != INVALID_TRACK_INDEX) {
+                if (!mVideoTrackMet) {
+                    if (index != mVideoTrackIndex) {
+                        SampleHolder sample =
+                                new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_NORMAL);
+                        mSampleHolder.flags =
+                                (mDecoderInputBuffer.isKeyFrame()
+                                        ? com.google.android.exoplayer.C.SAMPLE_FLAG_SYNC : 0)
+                                | (mDecoderInputBuffer.isDecodeOnly()
+                                        ? com.google.android.exoplayer.C.SAMPLE_FLAG_DECODE_ONLY
+                                        : 0);
+                        sample.timeUs = mDecoderInputBuffer.timeUs;
+                        sample.size = mDecoderInputBuffer.data.position();
+                        sample.ensureSpaceForWrite(sample.size);
+                        mDecoderInputBuffer.flip();
+                        sample.data.position(0);
+                        sample.data.put(mDecoderInputBuffer.data);
+                        sample.data.flip();
+                        mPendingSamples.add(new Pair<>(index, sample));
+                        return;
+                    }
+                    mVideoTrackMet = true;
+                    mBaseSamplePts =
+                            mDecoderInputBuffer.timeUs
+                                    - MpegTsDefaultAudioTrackRenderer
+                                            .INITIAL_AUDIO_BUFFERING_TIME_US;
+                    for (Pair<Integer, SampleHolder> pair : mPendingSamples) {
+                        if (pair.second.timeUs >= mBaseSamplePts) {
+                            mSampleBuffer.writeSample(pair.first, pair.second, conditionVariable);
+                        }
+                    }
+                    mPendingSamples.clear();
+                } else {
+                    if (mDecoderInputBuffer.timeUs < mBaseSamplePts
+                            && mVideoTrackIndex != index) {
+                        return;
+                    }
+                }
+            }
+            // Copy the decoder input to the sample holder.
+            mSampleHolder.clearData();
+            mSampleHolder.flags =
+                    (mDecoderInputBuffer.isKeyFrame()
+                            ? com.google.android.exoplayer.C.SAMPLE_FLAG_SYNC : 0)
+                    | (mDecoderInputBuffer.isDecodeOnly()
+                            ? com.google.android.exoplayer.C.SAMPLE_FLAG_DECODE_ONLY : 0);
+            mSampleHolder.timeUs = mDecoderInputBuffer.timeUs;
+            mSampleHolder.size = mDecoderInputBuffer.data.position();
+            mSampleHolder.ensureSpaceForWrite(mSampleHolder.size);
+            mDecoderInputBuffer.flip();
+            mSampleHolder.data.position(0);
+            mSampleHolder.data.put(mDecoderInputBuffer.data);
+            mSampleHolder.data.flip();
+            long writeStartTimeNs = SystemClock.elapsedRealtimeNanos();
+            mSampleBuffer.writeSample(index, mSampleHolder, conditionVariable);
 
-        // Checks whether the storage has enough bandwidth for recording samples.
-        if (mSampleBuffer.isWriteSpeedSlow(sample.size,
-                SystemClock.elapsedRealtimeNanos() - writeStartTimeNs)) {
-            mSampleBuffer.handleWriteSpeedSlow();
+            // Checks whether the storage has enough bandwidth for recording samples.
+            if (mSampleBuffer.isWriteSpeedSlow(mSampleHolder.size,
+                    SystemClock.elapsedRealtimeNanos() - writeStartTimeNs)) {
+                mSampleBuffer.handleWriteSpeedSlow();
+            }
         }
     }
 
@@ -328,7 +480,7 @@
     }
 
     @Override
-    public boolean continueBuffering(long positionUs)  {
+    public boolean continueBuffering(long positionUs) {
         return mSampleBuffer.continueBuffering(positionUs);
     }
 
@@ -386,12 +538,14 @@
     }
 
     private long getLastExtractedPositionUs() {
-        long lastExtractedPositionUs = Long.MAX_VALUE;
-        for (long value : mLastExtractedPositionUsMap.values()) {
-            lastExtractedPositionUs = Math.min(lastExtractedPositionUs, value);
+        long lastExtractedPositionUs = Long.MIN_VALUE;
+        for (Map.Entry<Integer, Long> entry : mLastExtractedPositionUsMap.entrySet()) {
+            if (mVideoTrackIndex != entry.getKey()) {
+                lastExtractedPositionUs = Math.max(lastExtractedPositionUs, entry.getValue());
+            }
         }
-        if (lastExtractedPositionUs == Long.MAX_VALUE) {
-            lastExtractedPositionUs = C.UNKNOWN_TIME_US;
+        if (lastExtractedPositionUs == Long.MIN_VALUE) {
+            lastExtractedPositionUs = com.google.android.exoplayer.C.UNKNOWN_TIME_US;
         }
         return lastExtractedPositionUs;
     }
diff --git a/src/com/android/tv/tuner/exoplayer/FileSampleExtractor.java b/src/com/android/tv/tuner/exoplayer/FileSampleExtractor.java
index ec7b4b1..b7e42a7 100644
--- a/src/com/android/tv/tuner/exoplayer/FileSampleExtractor.java
+++ b/src/com/android/tv/tuner/exoplayer/FileSampleExtractor.java
@@ -25,7 +25,6 @@
 import com.android.tv.tuner.tvinput.PlaybackBufferListener;
 
 import android.os.Handler;
-import android.util.Pair;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -61,18 +60,17 @@
 
     @Override
     public boolean prepare() throws IOException {
-        ArrayList<Pair<String, android.media.MediaFormat>> trackInfos =
-                mBufferManager.readTrackInfoFiles();
-        if (trackInfos == null || trackInfos.isEmpty()) {
+        List<BufferManager.TrackFormat> trackFormatList = mBufferManager.readTrackInfoFiles();
+        if (trackFormatList == null || trackFormatList.isEmpty()) {
             throw new IOException("Cannot find meta files for the recording.");
         }
-        mTrackCount = trackInfos.size();
+        mTrackCount = trackFormatList.size();
         List<String> ids = new ArrayList<>();
         mTrackFormats.clear();
         for (int i = 0; i < mTrackCount; ++i) {
-            Pair<String, android.media.MediaFormat> pair = trackInfos.get(i);
-            ids.add(pair.first);
-            mTrackFormats.add(MediaFormatUtil.createMediaFormat(pair.second));
+            BufferManager.TrackFormat trackFormat = trackFormatList.get(i);
+            ids.add(trackFormat.trackId);
+            mTrackFormats.add(MediaFormatUtil.createMediaFormat(trackFormat.format));
         }
         mSampleBuffer = new RecordingSampleBuffer(mBufferManager, mBufferListener, true,
                 RecordingSampleBuffer.BUFFER_REASON_RECORDED_PLAYBACK);
diff --git a/src/com/android/tv/tuner/exoplayer/MpegTsPlayer.java b/src/com/android/tv/tuner/exoplayer/MpegTsPlayer.java
index 381b22e..2694298 100644
--- a/src/com/android/tv/tuner/exoplayer/MpegTsPlayer.java
+++ b/src/com/android/tv/tuner/exoplayer/MpegTsPlayer.java
@@ -39,20 +39,22 @@
 import com.android.tv.tuner.data.Cea708Data;
 import com.android.tv.tuner.data.Cea708Data.CaptionEvent;
 import com.android.tv.tuner.data.TunerChannel;
-import com.android.tv.tuner.exoplayer.ac3.Ac3PassthroughTrackRenderer;
-import com.android.tv.tuner.exoplayer.ac3.Ac3TrackRenderer;
+import com.android.tv.tuner.exoplayer.audio.MpegTsDefaultAudioTrackRenderer;
+import com.android.tv.tuner.exoplayer.audio.MpegTsMediaCodecAudioTrackRenderer;
 import com.android.tv.tuner.source.TsDataSource;
 import com.android.tv.tuner.source.TsDataSourceManager;
 import com.android.tv.tuner.tvinput.EventDetector;
+import com.android.tv.tuner.tvinput.TunerDebug;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-/**
- * MPEG-2 TS stream player implementation using ExoPlayer.
- */
-public class MpegTsPlayer implements ExoPlayer.Listener, MediaCodecVideoTrackRenderer.EventListener,
-        Ac3PassthroughTrackRenderer.EventListener, Ac3TrackRenderer.Ac3EventListener {
+/** MPEG-2 TS stream player implementation using ExoPlayer. */
+public class MpegTsPlayer
+        implements ExoPlayer.Listener,
+                MediaCodecVideoTrackRenderer.EventListener,
+                MpegTsDefaultAudioTrackRenderer.EventListener,
+                MpegTsMediaCodecAudioTrackRenderer.Ac3EventListener {
     private int mCaptionServiceNumber = Cea708Data.EMPTY_SERVICE_NUMBER;
 
     /**
@@ -60,7 +62,7 @@
      */
     public interface RendererBuilder {
         void buildRenderers(MpegTsPlayer mpegTsPlayer, DataSource dataSource,
-                RendererBuilderCallback callback);
+                boolean hasSoftwareAudioDecoder, RendererBuilderCallback callback);
     }
 
     /**
@@ -94,6 +96,11 @@
         void onEmitCaptionEvent(CaptionEvent event);
 
         /**
+         * Notifies clearing up whole closed caption event.
+         */
+        void onClearCaptionEvent();
+
+        /**
          * Notifies the discovered caption service number.
          */
         void onDiscoverCaptionServiceNumber(int serviceNumber);
@@ -215,10 +222,11 @@
      * Creates renderers and {@link DataSource} and initializes player.
      * @param context a {@link Context} instance
      * @param channel to play
+     * @param hasSoftwareAudioDecoder {@code true} if there is connected software decoder
      * @param eventListener for program information which will be scanned from MPEG2-TS stream
      * @return true when everything is created and initialized well, false otherwise
      */
-    public boolean prepare(Context context, TunerChannel channel,
+    public boolean prepare(Context context, TunerChannel channel, boolean hasSoftwareAudioDecoder,
             EventDetector.EventListener eventListener) {
         TsDataSource source = null;
         if (channel != null) {
@@ -236,7 +244,7 @@
         }
         mRendererBuildingState = RENDERER_BUILDING_STATE_BUILDING;
         mBuilderCallback = new InternalRendererBuilderCallback();
-        mRendererBuilder.buildRenderers(this, source, mBuilderCallback);
+        mRendererBuilder.buildRenderers(this, source, hasSoftwareAudioDecoder, mBuilderCallback);
         return true;
     }
 
@@ -304,8 +312,10 @@
         SoftPreconditions.checkState(supportSmoothTrickPlay(playbackParams.getSpeed()));
         mPlayer.setPlayWhenReady(true);
         mTrickplayRunning = true;
-        if (mAudioRenderer instanceof Ac3PassthroughTrackRenderer) {
-            mPlayer.sendMessage(mAudioRenderer, Ac3PassthroughTrackRenderer.MSG_SET_PLAYBACK_SPEED,
+        if (mAudioRenderer instanceof MpegTsDefaultAudioTrackRenderer) {
+            mPlayer.sendMessage(
+                    mAudioRenderer,
+                    MpegTsDefaultAudioTrackRenderer.MSG_SET_PLAYBACK_SPEED,
                     playbackParams.getSpeed());
         } else {
             mPlayer.sendMessage(mAudioRenderer,
@@ -317,9 +327,9 @@
     private void stopSmoothTrickplay(boolean calledBySeek) {
         if (mTrickplayRunning) {
             mTrickplayRunning = false;
-            if (mAudioRenderer instanceof Ac3PassthroughTrackRenderer) {
-                mPlayer.sendMessage(mAudioRenderer,
-                        Ac3PassthroughTrackRenderer.MSG_SET_PLAYBACK_SPEED,
+            if (mAudioRenderer instanceof MpegTsDefaultAudioTrackRenderer) {
+                mPlayer.sendMessage(
+                        mAudioRenderer, MpegTsDefaultAudioTrackRenderer.MSG_SET_PLAYBACK_SPEED,
                         1.0f);
             } else {
                 mPlayer.sendMessage(mAudioRenderer,
@@ -423,8 +433,9 @@
      */
     public void setVolume(float volume) {
         mVolume = volume;
-        if (mAudioRenderer instanceof Ac3PassthroughTrackRenderer) {
-            mPlayer.sendMessage(mAudioRenderer, Ac3PassthroughTrackRenderer.MSG_SET_VOLUME, volume);
+        if (mAudioRenderer instanceof MpegTsDefaultAudioTrackRenderer) {
+            mPlayer.sendMessage(mAudioRenderer, MpegTsDefaultAudioTrackRenderer.MSG_SET_VOLUME,
+                    volume);
         } else {
             mPlayer.sendMessage(mAudioRenderer, MediaCodecAudioTrackRenderer.MSG_SET_VOLUME,
                     volume);
@@ -432,18 +443,20 @@
     }
 
     /**
-     * Enables or disables audio.
+     * Enables or disables audio and closed caption.
      *
-     * @param enable enables the audio when {@code true}, disables otherwise.
+     * @param enable enables the audio and closed caption when {@code true}, disables otherwise.
      */
-    public void setAudioTrack(boolean enable) {
-        if (mAudioRenderer instanceof Ac3PassthroughTrackRenderer) {
-            mPlayer.sendMessage(mAudioRenderer, Ac3PassthroughTrackRenderer.MSG_SET_AUDIO_TRACK,
+    public void setAudioTrackAndClosedCaption(boolean enable) {
+        if (mAudioRenderer instanceof MpegTsDefaultAudioTrackRenderer) {
+            mPlayer.sendMessage(mAudioRenderer, MpegTsDefaultAudioTrackRenderer.MSG_SET_AUDIO_TRACK,
                     enable ? 1 : 0);
         } else {
             mPlayer.sendMessage(mAudioRenderer, MediaCodecAudioTrackRenderer.MSG_SET_VOLUME,
                     enable ? mVolume : 0.0f);
         }
+        mPlayer.sendMessage(mTextRenderer, Cea708TextTrackRenderer.MSG_ENABLE_CLOSED_CAPTION,
+            enable);
     }
 
     /**
@@ -495,6 +508,28 @@
     }
 
     /**
+     * Returns the index of the currently selected track for the specified renderer.
+     *
+     * @param rendererIndex The index of the renderer.
+     * @return The selected track. A negative value or a value greater than or equal to the renderer's
+     *     track count indicates that the renderer is disabled.
+     */
+    public int getSelectedTrack(int rendererIndex) {
+        return mPlayer.getSelectedTrack(rendererIndex);
+    }
+
+    /**
+     * Returns the format of a track.
+     *
+     * @param rendererIndex The index of the renderer.
+     * @param trackIndex The index of the track.
+     * @return The format of the track.
+     */
+    public MediaFormat getTrackFormat(int rendererIndex, int trackIndex) {
+        return mPlayer.getTrackFormat(rendererIndex, trackIndex);
+    }
+
+    /**
      * Gets the main handler of the player.
      */
     /* package */ Handler getMainHandler() {
@@ -579,6 +614,7 @@
 
     @Override
     public void onDroppedFrames(int count, long elapsed) {
+        TunerDebug.notifyVideoFrameDrop(count, elapsed);
         if (mTrickplayRunning && mListener != null) {
             mListener.onSmoothTrickplayForceStopped();
         }
@@ -622,6 +658,13 @@
         }
 
         @Override
+        public void clearCaption() {
+            if (mVideoEventListener != null) {
+                mVideoEventListener.onClearCaptionEvent();
+            }
+        }
+
+        @Override
         public void discoverServiceNumber(int serviceNumber) {
             if (mVideoEventListener != null) {
                 mVideoEventListener.onDiscoverCaptionServiceNumber(serviceNumber);
@@ -650,4 +693,4 @@
             }
         }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/tuner/exoplayer/MpegTsRendererBuilder.java b/src/com/android/tv/tuner/exoplayer/MpegTsRendererBuilder.java
index 0e46c9c..006ccac 100644
--- a/src/com/android/tv/tuner/exoplayer/MpegTsRendererBuilder.java
+++ b/src/com/android/tv/tuner/exoplayer/MpegTsRendererBuilder.java
@@ -18,12 +18,14 @@
 
 import android.content.Context;
 
+import com.google.android.exoplayer.MediaCodecSelector;
 import com.google.android.exoplayer.SampleSource;
 import com.google.android.exoplayer.TrackRenderer;
 import com.google.android.exoplayer.upstream.DataSource;
+import com.android.tv.Features;
 import com.android.tv.tuner.exoplayer.MpegTsPlayer.RendererBuilder;
 import com.android.tv.tuner.exoplayer.MpegTsPlayer.RendererBuilderCallback;
-import com.android.tv.tuner.exoplayer.ac3.Ac3PassthroughTrackRenderer;
+import com.android.tv.tuner.exoplayer.audio.MpegTsDefaultAudioTrackRenderer;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
 import com.android.tv.tuner.tvinput.PlaybackBufferListener;
 
@@ -44,7 +46,7 @@
 
     @Override
     public void buildRenderers(MpegTsPlayer mpegTsPlayer, DataSource dataSource,
-            RendererBuilderCallback callback) {
+            boolean mHasSoftwareAudioDecoder, RendererBuilderCallback callback) {
         // Build the video and audio renderers.
         SampleExtractor extractor = dataSource == null ?
                 new MpegTsSampleExtractor(mBufferManager, mBufferListener) :
@@ -52,10 +54,16 @@
         SampleSource sampleSource = new MpegTsSampleSource(extractor);
         MpegTsVideoTrackRenderer videoRenderer = new MpegTsVideoTrackRenderer(mContext,
                 sampleSource, mpegTsPlayer.getMainHandler(), mpegTsPlayer);
-        // TODO: Only using Ac3PassthroughTrackRenderer for A/V sync issue. We will use
-        // {@link Ac3TrackRenderer} when we use ExoPlayer's extractor.
-        TrackRenderer audioRenderer = new Ac3PassthroughTrackRenderer(sampleSource,
-                mpegTsPlayer.getMainHandler(), mpegTsPlayer);
+        // TODO: Only using MpegTsDefaultAudioTrackRenderer for A/V sync issue. We will use
+        // {@link MpegTsMediaCodecAudioTrackRenderer} when we use ExoPlayer's extractor.
+        TrackRenderer audioRenderer =
+                new MpegTsDefaultAudioTrackRenderer(
+                        sampleSource,
+                        MediaCodecSelector.DEFAULT,
+                        mpegTsPlayer.getMainHandler(),
+                        mpegTsPlayer,
+                        mHasSoftwareAudioDecoder,
+                        !Features.AC3_SOFTWARE_DECODE.isEnabled(mContext));
         Cea708TextTrackRenderer textRenderer = new Cea708TextTrackRenderer(sampleSource);
 
         TrackRenderer[] renderers = new TrackRenderer[MpegTsPlayer.RENDERER_COUNT];
diff --git a/src/com/android/tv/tuner/exoplayer/ac3/AudioClock.java b/src/com/android/tv/tuner/exoplayer/audio/AudioClock.java
similarity index 98%
rename from src/com/android/tv/tuner/exoplayer/ac3/AudioClock.java
rename to src/com/android/tv/tuner/exoplayer/audio/AudioClock.java
index 600c2c8..5666c5b 100644
--- a/src/com/android/tv/tuner/exoplayer/ac3/AudioClock.java
+++ b/src/com/android/tv/tuner/exoplayer/audio/AudioClock.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.exoplayer.ac3;
+package com.android.tv.tuner.exoplayer.audio;
 
 import com.android.tv.common.SoftPreconditions;
 
diff --git a/src/com/android/tv/tuner/exoplayer/audio/AudioDecoder.java b/src/com/android/tv/tuner/exoplayer/audio/AudioDecoder.java
new file mode 100644
index 0000000..e581092
--- /dev/null
+++ b/src/com/android/tv/tuner/exoplayer/audio/AudioDecoder.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 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.tuner.exoplayer.audio;
+
+import com.google.android.exoplayer.ExoPlaybackException;
+import com.google.android.exoplayer.MediaFormat;
+import com.google.android.exoplayer.SampleHolder;
+
+import java.nio.ByteBuffer;
+
+/** A base class for audio decoders. */
+public abstract class AudioDecoder {
+
+    /**
+     * Decodes an audio sample.
+     *
+     * @param sampleHolder a holder that contains the sample data and corresponding metadata
+     */
+    public abstract void decode(SampleHolder sampleHolder);
+
+    /** Returns a decoded sample from decoder. */
+    public abstract ByteBuffer getDecodedSample();
+
+    /** Returns the presentation time for the decoded sample. */
+    public abstract long getDecodedTimeUs();
+
+    /**
+     * Clear previous decode state if any. Prepares to decode samples of the specified encoding.
+     * This method should be called before using decode.
+     *
+     * @param mime audio encoding
+     */
+    public abstract void resetDecoderState(String mimeType);
+
+    /** Releases all the resource. */
+    public abstract void release();
+
+    /**
+     * Init decoder if needed.
+     *
+     * @param format the format used to initialize decoder
+     */
+    public void maybeInitDecoder(MediaFormat format) throws ExoPlaybackException {
+        // Do nothing.
+    }
+
+    /** Returns input buffer that will be used in decoder. */
+    public ByteBuffer getInputBuffer() {
+        return null;
+    }
+
+    /** Returns the output format. */
+    public android.media.MediaFormat getOutputFormat() {
+        return null;
+    }
+}
diff --git a/src/com/android/tv/tuner/exoplayer/ac3/AudioTrackMonitor.java b/src/com/android/tv/tuner/exoplayer/audio/AudioTrackMonitor.java
similarity index 85%
rename from src/com/android/tv/tuner/exoplayer/ac3/AudioTrackMonitor.java
rename to src/com/android/tv/tuner/exoplayer/audio/AudioTrackMonitor.java
index bfdf08a..ec616b1 100644
--- a/src/com/android/tv/tuner/exoplayer/ac3/AudioTrackMonitor.java
+++ b/src/com/android/tv/tuner/exoplayer/audio/AudioTrackMonitor.java
@@ -14,12 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.exoplayer.ac3;
+package com.android.tv.tuner.exoplayer.audio;
 
 import android.os.SystemClock;
 import android.util.Log;
 import android.util.Pair;
 
+import com.google.android.exoplayer.util.MimeTypes;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Set;
@@ -35,7 +36,7 @@
     private final ArrayList<Pair<Long, Integer>> mPtsList = new ArrayList<>();
     private final Set<Integer> mSampleSize = new HashSet<>();
     private final Set<Integer> mCurSampleSize = new HashSet<>();
-    private final Set<Integer> mAc3Header = new HashSet<>();
+    private final Set<Integer> mHeader = new HashSet<>();
 
     private long mExpireMs;
     private long mDuration;
@@ -43,6 +44,8 @@
     private long mTotalCount;
     private long mStartMs;
 
+    private boolean mIsMp2;
+
     private void flush() {
         mExpireMs += mDuration;
         mSampleCount = 0;
@@ -61,10 +64,14 @@
         mTotalCount = 0;
         mStartMs = 0;
         mSampleSize.clear();
-        mAc3Header.clear();
+        mHeader.clear();
         flush();
     }
 
+    public void setEncoding(String mime) {
+        mIsMp2 = MimeTypes.AUDIO_MPEG_L2.equalsIgnoreCase(mime);
+    }
+
     /**
      * Adds an audio sample information for monitoring.
      *
@@ -76,7 +83,7 @@
         mTotalCount++;
         mSampleCount++;
         mSampleSize.add(sampleSize);
-        mAc3Header.add(header);
+        mHeader.add(header);
         mCurSampleSize.add(sampleSize);
         if (mTotalCount == 1) {
             mStartMs = SystemClock.elapsedRealtime();
@@ -98,8 +105,9 @@
         long now = SystemClock.elapsedRealtime();
         if (mExpireMs != 0 && now >= mExpireMs) {
             if (DEBUG) {
-                long sampleDuration = (mTotalCount - 1) *
-                        Ac3PassthroughTrackRenderer.AC3_SAMPLE_DURATION_US / 1000;
+                long unitDuration = mIsMp2 ? MpegTsDefaultAudioTrackRenderer.MP2_SAMPLE_DURATION_US
+                        : MpegTsDefaultAudioTrackRenderer.AC3_SAMPLE_DURATION_US;
+                long sampleDuration = (mTotalCount - 1) * unitDuration / 1000;
                 long totalDuration = now - mStartMs;
                 StringBuilder ptsBuilder = new StringBuilder();
                 ptsBuilder.append("PTS received ").append(mSampleCount).append(", ")
@@ -113,7 +121,7 @@
             }
             if (DEBUG || mCurSampleSize.size() > 1) {
                 Log.d(TAG, "PTS received sample size: "
-                        + String.valueOf(mSampleSize) + mCurSampleSize + mAc3Header);
+                        + String.valueOf(mSampleSize) + mCurSampleSize + mHeader);
             }
             flush();
         }
diff --git a/src/com/android/tv/tuner/exoplayer/ac3/AudioTrackWrapper.java b/src/com/android/tv/tuner/exoplayer/audio/AudioTrackWrapper.java
similarity index 84%
rename from src/com/android/tv/tuner/exoplayer/ac3/AudioTrackWrapper.java
rename to src/com/android/tv/tuner/exoplayer/audio/AudioTrackWrapper.java
index bc3c5d0..953c9fc 100644
--- a/src/com/android/tv/tuner/exoplayer/ac3/AudioTrackWrapper.java
+++ b/src/com/android/tv/tuner/exoplayer/audio/AudioTrackWrapper.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.exoplayer.ac3;
+package com.android.tv.tuner.exoplayer.audio;
 
 import android.media.MediaFormat;
 
+import com.google.android.exoplayer.C;
 import com.google.android.exoplayer.audio.AudioTrack;
 
 import java.nio.ByteBuffer;
@@ -28,6 +29,10 @@
  * This wrapper class will do nothing in disabled status for those operations.
  */
 public class AudioTrackWrapper {
+    private static final int PCM16_FRAME_BYTES = 2;
+    private static final int AC3_FRAMES_IN_ONE_SAMPLE = 1536;
+    private static final int BUFFERED_SAMPLES_IN_AUDIOTRACK =
+            MpegTsDefaultAudioTrackRenderer.BUFFERED_SAMPLES_IN_AUDIOTRACK;
     private final AudioTrack mAudioTrack = new AudioTrack();
     private int mAudioSessionID;
     private boolean mIsEnabled;
@@ -106,7 +111,7 @@
         mAudioTrack.setVolume(volume);
     }
 
-    public void reconfigure(MediaFormat format) {
+    public void reconfigure(MediaFormat format, int audioBufferSize) {
         if (!mIsEnabled || format == null) {
             return;
         }
@@ -117,9 +122,9 @@
         try {
             pcmEncoding = format.getInteger(MediaFormat.KEY_PCM_ENCODING);
         } catch (Exception e) {
-            pcmEncoding = com.google.android.exoplayer.MediaFormat.NO_VALUE;
+            pcmEncoding = C.ENCODING_PCM_16BIT;
         }
-        // TODO: Handle non-AC3 or non-passthrough audio.
+        // TODO: Handle non-AC3.
         if (MediaFormat.MIMETYPE_AUDIO_AC3.equalsIgnoreCase(mimeType) && channelCount != 2) {
             // Workarounds b/25955476.
             // Since all devices and platforms does not support passthrough for non-stereo AC3,
@@ -127,7 +132,14 @@
             // In other words, the channel count should be always 2.
             channelCount = 2;
         }
-        mAudioTrack.configure(mimeType, channelCount, sampleRate, pcmEncoding);
+        if (MediaFormat.MIMETYPE_AUDIO_RAW.equalsIgnoreCase(mimeType)) {
+            audioBufferSize =
+                    channelCount
+                            * PCM16_FRAME_BYTES
+                            * AC3_FRAMES_IN_ONE_SAMPLE
+                            * BUFFERED_SAMPLES_IN_AUDIOTRACK;
+        }
+        mAudioTrack.configure(mimeType, channelCount, sampleRate, pcmEncoding, audioBufferSize);
     }
 
     public void handleDiscontinuity() {
diff --git a/src/com/android/tv/tuner/exoplayer/audio/MediaCodecAudioDecoder.java b/src/com/android/tv/tuner/exoplayer/audio/MediaCodecAudioDecoder.java
new file mode 100644
index 0000000..72bc68b
--- /dev/null
+++ b/src/com/android/tv/tuner/exoplayer/audio/MediaCodecAudioDecoder.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2017 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.tuner.exoplayer.audio;
+
+import android.media.MediaCodec;
+import android.util.Log;
+
+import com.google.android.exoplayer.CodecCounters;
+import com.google.android.exoplayer.DecoderInfo;
+import com.google.android.exoplayer.ExoPlaybackException;
+import com.google.android.exoplayer.MediaCodecSelector;
+import com.google.android.exoplayer.MediaCodecUtil;
+import com.google.android.exoplayer.MediaFormat;
+import com.google.android.exoplayer.SampleHolder;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+
+/** A decoder to use MediaCodec for decoding audio stream. */
+public class MediaCodecAudioDecoder extends AudioDecoder {
+    private static final String TAG = "MediaCodecAudioDecoder";
+
+    public static final int INDEX_INVALID = -1;
+
+    private final CodecCounters mCodecCounters;
+    private final MediaCodecSelector mSelector;
+
+    private MediaCodec mCodec;
+    private MediaCodec.BufferInfo mOutputBufferInfo;
+    private ByteBuffer mMediaCodecOutputBuffer;
+    private ArrayList<Long> mDecodeOnlyPresentationTimestamps;
+    private boolean mWaitingForFirstSyncFrame;
+    private boolean mIsNewIndex;
+    private int mInputIndex;
+    private int mOutputIndex;
+
+    /** Creates a MediaCodec based audio decoder. */
+    public MediaCodecAudioDecoder(MediaCodecSelector selector) {
+        mSelector = selector;
+        mOutputBufferInfo = new MediaCodec.BufferInfo();
+        mCodecCounters = new CodecCounters();
+        mDecodeOnlyPresentationTimestamps = new ArrayList<>();
+    }
+
+    /** Returns {@code true} if there is decoder for {@code mimeType}. */
+    public static boolean supportMimeType(MediaCodecSelector selector, String mimeType) {
+        if (selector == null) {
+            return false;
+        }
+        return getDecoderInfo(selector, mimeType) != null;
+    }
+
+    private static DecoderInfo getDecoderInfo(MediaCodecSelector selector, String mimeType) {
+        try {
+            return selector.getDecoderInfo(mimeType, false);
+        } catch (MediaCodecUtil.DecoderQueryException e) {
+            Log.e(TAG, "Select decoder error:" + e);
+            return null;
+        }
+    }
+
+    private boolean shouldInitCodec(MediaFormat format) {
+        return format != null && mCodec == null;
+    }
+
+    @Override
+    public void maybeInitDecoder(MediaFormat format) throws ExoPlaybackException {
+        if (!shouldInitCodec(format)) {
+            return;
+        }
+
+        String mimeType = format.mimeType;
+        DecoderInfo decoderInfo = getDecoderInfo(mSelector, mimeType);
+        if (decoderInfo == null) {
+            Log.i(TAG, "There is not decoder found for " + mimeType);
+            return;
+        }
+
+        String codecName = decoderInfo.name;
+        try {
+            mCodec = MediaCodec.createByCodecName(codecName);
+            mCodec.configure(format.getFrameworkMediaFormatV16(), null, null, 0);
+            mCodec.start();
+        } catch (Exception e) {
+            Log.e(TAG, "Failed when configure or start codec:" + e);
+            throw new ExoPlaybackException(e);
+        }
+        mInputIndex = INDEX_INVALID;
+        mOutputIndex = INDEX_INVALID;
+        mWaitingForFirstSyncFrame = true;
+        mCodecCounters.codecInitCount++;
+    }
+
+    @Override
+    public void resetDecoderState(String mimeType) {
+        if (mCodec == null) {
+            return;
+        }
+        mInputIndex = INDEX_INVALID;
+        mOutputIndex = INDEX_INVALID;
+        mDecodeOnlyPresentationTimestamps.clear();
+        mCodec.flush();
+        mWaitingForFirstSyncFrame = true;
+    }
+
+    @Override
+    public void release() {
+        if (mCodec != null) {
+            mDecodeOnlyPresentationTimestamps.clear();
+            mInputIndex = INDEX_INVALID;
+            mOutputIndex = INDEX_INVALID;
+            mCodecCounters.codecReleaseCount++;
+            try {
+                mCodec.stop();
+            } finally {
+                try {
+                    mCodec.release();
+                } finally {
+                    mCodec = null;
+                }
+            }
+        }
+    }
+
+    /** Returns the index of input buffer which is ready for using. */
+    public int getInputIndex() {
+        return mInputIndex;
+    }
+
+    @Override
+    public ByteBuffer getInputBuffer() {
+        if (mInputIndex < 0) {
+            mInputIndex = mCodec.dequeueInputBuffer(0);
+            if (mInputIndex < 0) {
+                return null;
+            }
+            return mCodec.getInputBuffer(mInputIndex);
+        }
+        return mCodec.getInputBuffer(mInputIndex);
+    }
+
+    @Override
+    public void decode(SampleHolder sampleHolder) {
+        if (mWaitingForFirstSyncFrame) {
+            if (!sampleHolder.isSyncFrame()) {
+                sampleHolder.clearData();
+                return;
+            }
+            mWaitingForFirstSyncFrame = false;
+        }
+        long presentationTimeUs = sampleHolder.timeUs;
+        if (sampleHolder.isDecodeOnly()) {
+            mDecodeOnlyPresentationTimestamps.add(presentationTimeUs);
+        }
+        mCodec.queueInputBuffer(mInputIndex, 0, sampleHolder.data.limit(), presentationTimeUs, 0);
+        mInputIndex = INDEX_INVALID;
+        mCodecCounters.inputBufferCount++;
+    }
+
+    private int getDecodeOnlyIndex(long presentationTimeUs) {
+        final int size = mDecodeOnlyPresentationTimestamps.size();
+        for (int i = 0; i < size; i++) {
+            if (mDecodeOnlyPresentationTimestamps.get(i).longValue() == presentationTimeUs) {
+                return i;
+            }
+        }
+        return INDEX_INVALID;
+    }
+
+    /** Returns the index of output buffer which is ready for using. */
+    public int getOutputIndex() {
+        if (mOutputIndex < 0) {
+            mOutputIndex = mCodec.dequeueOutputBuffer(mOutputBufferInfo, 0);
+            mIsNewIndex = true;
+        } else {
+            mIsNewIndex = false;
+        }
+        return mOutputIndex;
+    }
+
+    @Override
+    public android.media.MediaFormat getOutputFormat() {
+        return mCodec.getOutputFormat();
+    }
+
+    /** Returns {@code true} if the output is only for decoding but not for rendering. */
+    public boolean maybeDecodeOnlyIndex() {
+        int decodeOnlyIndex = getDecodeOnlyIndex(mOutputBufferInfo.presentationTimeUs);
+        if (decodeOnlyIndex != INDEX_INVALID) {
+            mCodec.releaseOutputBuffer(mOutputIndex, false);
+            mCodecCounters.skippedOutputBufferCount++;
+            mDecodeOnlyPresentationTimestamps.remove(decodeOnlyIndex);
+            mOutputIndex = INDEX_INVALID;
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public ByteBuffer getDecodedSample() {
+        if (maybeDecodeOnlyIndex() || mOutputIndex < 0) {
+            return null;
+        }
+        if (mIsNewIndex) {
+            mMediaCodecOutputBuffer = mCodec.getOutputBuffer(mOutputIndex);
+        }
+        return mMediaCodecOutputBuffer;
+    }
+
+    @Override
+    public long getDecodedTimeUs() {
+        return mOutputBufferInfo.presentationTimeUs;
+    }
+
+    /** Releases the output buffer after rendering. */
+    public void releaseOutputBuffer() {
+        mCodecCounters.renderedOutputBufferCount++;
+        mCodec.releaseOutputBuffer(mOutputIndex, false);
+        mOutputIndex = INDEX_INVALID;
+    }
+}
diff --git a/src/com/android/tv/tuner/exoplayer/ac3/Ac3PassthroughTrackRenderer.java b/src/com/android/tv/tuner/exoplayer/audio/MpegTsDefaultAudioTrackRenderer.java
similarity index 60%
rename from src/com/android/tv/tuner/exoplayer/ac3/Ac3PassthroughTrackRenderer.java
rename to src/com/android/tv/tuner/exoplayer/audio/MpegTsDefaultAudioTrackRenderer.java
index 9dae2e3..7717041 100644
--- a/src/com/android/tv/tuner/exoplayer/ac3/Ac3PassthroughTrackRenderer.java
+++ b/src/com/android/tv/tuner/exoplayer/audio/MpegTsDefaultAudioTrackRenderer.java
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.exoplayer.ac3;
+package com.android.tv.tuner.exoplayer.audio;
 
+import android.media.MediaCodec;
+import android.os.Build;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Log;
@@ -23,16 +25,16 @@
 import com.google.android.exoplayer.CodecCounters;
 import com.google.android.exoplayer.ExoPlaybackException;
 import com.google.android.exoplayer.MediaClock;
-import com.google.android.exoplayer.MediaCodecAudioTrackRenderer;
+import com.google.android.exoplayer.MediaCodecSelector;
 import com.google.android.exoplayer.MediaFormat;
 import com.google.android.exoplayer.MediaFormatHolder;
-import com.google.android.exoplayer.MediaFormatUtil;
 import com.google.android.exoplayer.SampleHolder;
 import com.google.android.exoplayer.SampleSource;
 import com.google.android.exoplayer.TrackRenderer;
 import com.google.android.exoplayer.audio.AudioTrack;
 import com.google.android.exoplayer.util.Assertions;
 import com.google.android.exoplayer.util.MimeTypes;
+import com.android.tv.tuner.exoplayer.ffmpeg.FfmpegDecoderClient;
 import com.android.tv.tuner.tvinput.TunerDebug;
 
 import java.io.IOException;
@@ -40,9 +42,10 @@
 import java.util.ArrayList;
 
 /**
- * Decodes and renders AC3 audio.
+ * Decodes and renders DTV audio. Supports MediaCodec based decoding, passthrough playback and
+ * ffmpeg based software decoding (AC3, MP2).
  */
-public class Ac3PassthroughTrackRenderer extends TrackRenderer implements MediaClock {
+public class MpegTsDefaultAudioTrackRenderer extends TrackRenderer implements MediaClock {
     public static final int MSG_SET_VOLUME = 10000;
     public static final int MSG_SET_AUDIO_TRACK = MSG_SET_VOLUME + 1;
     public static final int MSG_SET_PLAYBACK_SPEED = MSG_SET_VOLUME + 2;
@@ -51,7 +54,19 @@
     // One AC3 sample has 1536 frames, and its duration is 32ms.
     public static final long AC3_SAMPLE_DURATION_US = 32000;
 
-    private static final String TAG = "Ac3PassthroughTrackRenderer";
+    // TODO: Check whether DVB broadcasting uses sample rate other than 48Khz.
+    // MPEG-1 audio Layer II and III has 1152 frames per sample.
+    // 1152 frames duration is 24ms when sample rate is 48Khz.
+    static final long MP2_SAMPLE_DURATION_US = 24000;
+
+    // This is around 150ms, 150ms is big enough not to under-run AudioTrack,
+    // and  150ms is also small enough to fill the buffer rapidly.
+    static int BUFFERED_SAMPLES_IN_AUDIOTRACK = 5;
+    public static final long INITIAL_AUDIO_BUFFERING_TIME_US =
+            BUFFERED_SAMPLES_IN_AUDIOTRACK * AC3_SAMPLE_DURATION_US;
+
+
+    private static final String TAG = "MpegTsDefaultAudioTrac";
     private static final boolean DEBUG = false;
 
     /**
@@ -67,6 +82,8 @@
     private static final int DEFAULT_OUTPUT_BUFFER_SIZE = 1024*1024;
     private static final int MONITOR_DURATION_MS = 1000;
     private static final int AC3_HEADER_BITRATE_OFFSET = 4;
+    private static final int MP2_HEADER_BITRATE_OFFSET = 2;
+    private static final int MP2_HEADER_BITRATE_MASK = 0xfc;
 
     // Keep this as static in order to prevent new framework AudioTrack creation
     // while old AudioTrack is being released.
@@ -83,17 +100,25 @@
     // PTS interpolated time should be delayed reasonably when AudioTrack is not used.
     private static final long ESTIMATED_TRACK_RENDERING_DELAY_US = 500000;
 
+    private final MediaCodecSelector mSelector;
+
     private final CodecCounters mCodecCounters;
     private final SampleSource.SampleSourceReader mSource;
-    private final SampleHolder mSampleHolder;
     private final MediaFormatHolder mFormatHolder;
     private final EventListener mEventListener;
     private final Handler mEventHandler;
     private final AudioTrackMonitor mMonitor;
     private final AudioClock mAudioClock;
+    private final boolean mAc3Passthrough;
+    private final boolean mSoftwareDecoderAvailable;
 
     private MediaFormat mFormat;
+    private SampleHolder mSampleHolder;
+    private String mDecodingMime;
+    private boolean mFormatConfigured;
+    private int mSampleSize;
     private final ByteBuffer mOutputBuffer;
+    private AudioDecoder mAudioDecoder;
     private boolean mOutputReady;
     private int mTrackIndex;
     private boolean mSourceStateReady;
@@ -106,16 +131,23 @@
     private long mInterpolatedTimeUs;
     private long mPreviousPositionUs;
     private boolean mIsStopped;
+    private boolean mEnabled = true;
+    private boolean mIsMuted;
     private ArrayList<Integer> mTracksIndex;
+    private boolean mUseFrameworkDecoder;
 
-    public Ac3PassthroughTrackRenderer(SampleSource source, Handler eventHandler,
-            EventListener listener) {
+    public MpegTsDefaultAudioTrackRenderer(
+            SampleSource source,
+            MediaCodecSelector selector,
+            Handler eventHandler,
+            EventListener listener,
+            boolean hasSoftwareAudioDecoder,
+            boolean usePassthrough) {
         mSource = source.register();
+        mSelector = selector;
         mEventHandler = eventHandler;
         mEventListener = listener;
         mTrackIndex = -1;
-        mSampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DIRECT);
-        mSampleHolder.ensureSpaceForWrite(DEFAULT_INPUT_BUFFER_SIZE);
         mOutputBuffer = ByteBuffer.allocate(DEFAULT_OUTPUT_BUFFER_SIZE);
         mFormatHolder = new MediaFormatHolder();
         AUDIO_TRACK.restart();
@@ -123,6 +155,8 @@
         mMonitor = new AudioTrackMonitor();
         mAudioClock = new AudioClock();
         mTracksIndex = new ArrayList<>();
+        mAc3Passthrough = usePassthrough;
+        mSoftwareDecoderAvailable = hasSoftwareAudioDecoder && FfmpegDecoderClient.isAvailable();
     }
 
     @Override
@@ -130,8 +164,11 @@
         return this;
     }
 
-    private static boolean handlesMimeType(String mimeType) {
-        return mimeType.equals(MimeTypes.AUDIO_AC3) || mimeType.equals(MimeTypes.AUDIO_E_AC3);
+    private boolean handlesMimeType(String mimeType) {
+        return mimeType.equals(MimeTypes.AUDIO_AC3)
+                || mimeType.equals(MimeTypes.AUDIO_E_AC3)
+                || mimeType.equals(MimeTypes.AUDIO_MPEG_L2)
+                || MediaCodecAudioDecoder.supportMimeType(mSelector, mimeType);
     }
 
     @Override
@@ -141,7 +178,8 @@
             return false;
         }
         for (int i = 0; i < mSource.getTrackCount(); i++) {
-            if (handlesMimeType(mSource.getFormat(i).mimeType)) {
+            String mimeType = mSource.getFormat(i).mimeType;
+            if (MimeTypes.isAudio(mimeType) && handlesMimeType(mimeType)) {
                 if (mTrackIndex < 0) {
                     mTrackIndex = i;
                 }
@@ -174,7 +212,9 @@
 
     @Override
     protected void onDisabled() {
-        AUDIO_TRACK.resetSessionId();
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+            AUDIO_TRACK.resetSessionId();
+        }
         clearDecodeState();
         mFormat = null;
         mSource.disable(mTrackIndex);
@@ -182,6 +222,7 @@
 
     @Override
     protected void onReleased() {
+        releaseDecoder();
         AUDIO_TRACK.release();
         mSource.release();
     }
@@ -213,9 +254,12 @@
     protected void seekTo(long positionUs) {
         mSource.seekToUs(positionUs);
         AUDIO_TRACK.reset();
-        // resetSessionId() will create a new framework AudioTrack instead of reusing old one.
-        AUDIO_TRACK.resetSessionId();
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
+            // resetSessionId() will create a new framework AudioTrack instead of reusing old one.
+            AUDIO_TRACK.resetSessionId();
+        }
         seekToInternal(positionUs);
+        clearDecodeState();
     }
 
     @Override
@@ -274,7 +318,10 @@
                 return;
             }
 
-            // Process only one sample at a time for doSomeWork()
+            if (mAudioDecoder != null) {
+                mAudioDecoder.maybeInitDecoder(mFormat);
+            }
+            // Process only one sample at a time for doSomeWork() when using FFmpeg decoder.
             if (processOutput()) {
                 if (!mOutputReady) {
                     while (feedInputBuffer()) {
@@ -314,9 +361,18 @@
 
     private void clearDecodeState() {
         mOutputReady = false;
+        if (mAudioDecoder != null) {
+            mAudioDecoder.resetDecoderState(mDecodingMime);
+        }
         AUDIO_TRACK.reset();
     }
 
+    private void releaseDecoder() {
+        if (mAudioDecoder != null) {
+            mAudioDecoder.release();
+        }
+    }
+
     private void readFormat() throws IOException, ExoPlaybackException {
         int result = mSource.readData(mTrackIndex, mCurrentPositionUs,
                 mFormatHolder, mSampleHolder);
@@ -325,14 +381,69 @@
         }
     }
 
+    private MediaFormat convertMediaFormatToRaw(MediaFormat format) {
+        return MediaFormat.createAudioFormat(
+                format.trackId,
+                MimeTypes.AUDIO_RAW,
+                format.bitrate,
+                format.maxInputSize,
+                format.durationUs,
+                format.channelCount,
+                format.sampleRate,
+                format.initializationData,
+                format.language);
+    }
+
     private void onInputFormatChanged(MediaFormatHolder formatHolder)
             throws ExoPlaybackException {
-        mFormat = formatHolder.format;
-        if (DEBUG) {
+        String mimeType = formatHolder.format.mimeType;
+        mUseFrameworkDecoder = MediaCodecAudioDecoder.supportMimeType(mSelector, mimeType);
+        if (mUseFrameworkDecoder) {
+            mAudioDecoder = new MediaCodecAudioDecoder(mSelector);
+            mFormat = formatHolder.format;
+            mAudioDecoder.maybeInitDecoder(mFormat);
+            mSampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED);
+        } else if (mSoftwareDecoderAvailable
+                && (MimeTypes.AUDIO_MPEG_L2.equalsIgnoreCase(mimeType)
+                        || MimeTypes.AUDIO_AC3.equalsIgnoreCase(mimeType) && !mAc3Passthrough)) {
+            releaseDecoder();
+            mSampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DIRECT);
+            mSampleHolder.ensureSpaceForWrite(DEFAULT_INPUT_BUFFER_SIZE);
+            mAudioDecoder = FfmpegDecoderClient.getInstance();
+            mDecodingMime = mimeType;
+            mFormat = convertMediaFormatToRaw(formatHolder.format);
+        } else {
+            mSampleHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DIRECT);
+            mSampleHolder.ensureSpaceForWrite(DEFAULT_INPUT_BUFFER_SIZE);
+            mFormat = formatHolder.format;
+            releaseDecoder();
+        }
+        mFormatConfigured = true;
+        mMonitor.setEncoding(mimeType);
+        if (DEBUG && !mUseFrameworkDecoder) {
             Log.d(TAG, "AudioTrack was configured to FORMAT: " + mFormat.toString());
         }
         clearDecodeState();
-        AUDIO_TRACK.reconfigure(mFormat.getFrameworkMediaFormatV16());
+        if (!mUseFrameworkDecoder) {
+            AUDIO_TRACK.reconfigure(mFormat.getFrameworkMediaFormatV16(), 0);
+        }
+    }
+
+    private void onSampleSizeChanged(int sampleSize) {
+        if (DEBUG) {
+            Log.d(TAG, "Sample size was changed to : " + sampleSize);
+        }
+        clearDecodeState();
+        int audioBufferSize = sampleSize * BUFFERED_SAMPLES_IN_AUDIOTRACK;
+        mSampleSize = sampleSize;
+        AUDIO_TRACK.reconfigure(mFormat.getFrameworkMediaFormatV16(), audioBufferSize);
+    }
+
+    private void onOutputFormatChanged(android.media.MediaFormat format) {
+        if (DEBUG) {
+            Log.d(TAG, "AudioTrack was configured to FORMAT: " + format.toString());
+        }
+        AUDIO_TRACK.reconfigure(format, 0);
     }
 
     private boolean feedInputBuffer() throws IOException, ExoPlaybackException {
@@ -340,10 +451,24 @@
             return false;
         }
 
-        mSampleHolder.data.clear();
-        mSampleHolder.size = 0;
-        int result = mSource.readData(mTrackIndex, mPresentationTimeUs, mFormatHolder,
-                mSampleHolder);
+        if (mUseFrameworkDecoder) {
+            boolean indexChanged =
+                    ((MediaCodecAudioDecoder) mAudioDecoder).getInputIndex()
+                            == MediaCodecAudioDecoder.INDEX_INVALID;
+            if (indexChanged) {
+                mSampleHolder.data = mAudioDecoder.getInputBuffer();
+                if (mSampleHolder.data != null) {
+                    mSampleHolder.clearData();
+                } else {
+                    return false;
+                }
+            }
+        } else {
+            mSampleHolder.data.clear();
+            mSampleHolder.size = 0;
+        }
+        int result =
+                mSource.readData(mTrackIndex, mPresentationTimeUs, mFormatHolder, mSampleHolder);
         switch (result) {
             case SampleSource.NOTHING_READ: {
                 return false;
@@ -359,8 +484,48 @@
                 return false;
             }
             default: {
+                if (mSampleHolder.size != mSampleSize
+                        && mFormatConfigured
+                        && !mUseFrameworkDecoder) {
+                    onSampleSizeChanged(mSampleHolder.size);
+                }
                 mSampleHolder.data.flip();
-                decodeDone(mSampleHolder.data, mSampleHolder.timeUs);
+                if (!mUseFrameworkDecoder) {
+                    if (MimeTypes.AUDIO_MPEG_L2.equalsIgnoreCase(mDecodingMime)) {
+                        mMonitor.addPts(
+                            mSampleHolder.timeUs,
+                            mOutputBuffer.position(),
+                            mSampleHolder.data.get(MP2_HEADER_BITRATE_OFFSET)
+                                & MP2_HEADER_BITRATE_MASK);
+                    } else {
+                        mMonitor.addPts(
+                            mSampleHolder.timeUs,
+                            mOutputBuffer.position(),
+                            mSampleHolder.data.get(AC3_HEADER_BITRATE_OFFSET) & 0xff);
+                    }
+                }
+                if (mAudioDecoder != null) {
+                    mAudioDecoder.decode(mSampleHolder);
+                    if (mUseFrameworkDecoder) {
+                        int outputIndex =
+                                ((MediaCodecAudioDecoder) mAudioDecoder).getOutputIndex();
+                        if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                            onOutputFormatChanged(mAudioDecoder.getOutputFormat());
+                            return true;
+                        } else if (outputIndex < 0) {
+                            return true;
+                        }
+                        if (((MediaCodecAudioDecoder) mAudioDecoder).maybeDecodeOnlyIndex()) {
+                            AUDIO_TRACK.handleDiscontinuity();
+                            return true;
+                        }
+                    }
+                    ByteBuffer outputBuffer = mAudioDecoder.getDecodedSample();
+                    long presentationTimeUs = mAudioDecoder.getDecodedTimeUs();
+                    decodeDone(outputBuffer, presentationTimeUs);
+                } else {
+                    decodeDone(mSampleHolder.data, mSampleHolder.timeUs);
+                }
                 return true;
             }
         }
@@ -383,15 +548,22 @@
         int handleBufferResult;
         try {
             // To reduce discontinuity, interpolate presentation time.
-            mInterpolatedTimeUs = mPresentationTimeUs
+            if (MimeTypes.AUDIO_MPEG_L2.equalsIgnoreCase(mDecodingMime)) {
+                mInterpolatedTimeUs = mPresentationTimeUs
+                    + mPresentationCount * MP2_SAMPLE_DURATION_US;
+            } else if (!mUseFrameworkDecoder) {
+                mInterpolatedTimeUs = mPresentationTimeUs
                     + mPresentationCount * AC3_SAMPLE_DURATION_US;
-            handleBufferResult = AUDIO_TRACK.handleBuffer(mOutputBuffer,
-                    0, mOutputBuffer.limit(), mInterpolatedTimeUs);
+            } else {
+                mInterpolatedTimeUs = mPresentationTimeUs;
+            }
+            handleBufferResult =
+                    AUDIO_TRACK.handleBuffer(
+                            mOutputBuffer, 0, mOutputBuffer.limit(), mInterpolatedTimeUs);
         } catch (AudioTrack.WriteException e) {
             notifyAudioTrackWriteError(e);
             throw new ExoPlaybackException(e);
         }
-
         if ((handleBufferResult & AudioTrack.RESULT_POSITION_DISCONTINUITY) != 0) {
             Log.i(TAG, "Play discontinuity happened");
             mCurrentPositionUs = Long.MIN_VALUE;
@@ -399,6 +571,9 @@
         if ((handleBufferResult & AudioTrack.RESULT_BUFFER_CONSUMED) != 0) {
             mCodecCounters.renderedOutputBufferCount++;
             mOutputReady = false;
+            if (mUseFrameworkDecoder) {
+                ((MediaCodecAudioDecoder) mAudioDecoder).releaseOutputBuffer();
+            }
             return true;
         }
         return false;
@@ -421,7 +596,7 @@
         if (!AUDIO_TRACK.isInitialized()) {
             return mAudioClock.getPositionUs();
         } else if (!AUDIO_TRACK.isEnabled()) {
-            if (mInterpolatedTimeUs > 0) {
+            if (mInterpolatedTimeUs > 0 && !mUseFrameworkDecoder) {
                 return mInterpolatedTimeUs - ESTIMATED_TRACK_RENDERING_DELAY_US;
             }
             return mPresentationTimeUs;
@@ -471,8 +646,6 @@
         Assertions.checkState(mOutputBuffer.remaining() >= outputBuffer.limit());
 
         mOutputBuffer.put(outputBuffer);
-        mMonitor.addPts(presentationTimeUs, mOutputBuffer.position(),
-                mOutputBuffer.get(AC3_HEADER_BITRATE_OFFSET));
         if (presentationTimeUs == mPresentationTimeUs) {
             mPresentationCount++;
         } else {
@@ -511,24 +684,29 @@
     public void handleMessage(int messageType, Object message) throws ExoPlaybackException {
         switch (messageType) {
             case MSG_SET_VOLUME:
-                AUDIO_TRACK.setVolume((Float) message);
+                float volume = (Float) message;
+                // Workaround: we cannot mute the audio track by setting the volume to 0, we need to
+                // disable the AUDIO_TRACK for this intent. However, enabling/disabling audio track
+                // whenever volume is being set might cause side effects, therefore we only handle
+                // "explicit mute operations", i.e., only after certain non-zero volume has been
+                // set, the subsequent volume setting operations will be consider as mute/un-mute
+                // operations and thus enable/disable the audio track.
+                if (mIsMuted && volume > 0) {
+                    mIsMuted = false;
+                    if (mEnabled) {
+                        setStatus(true);
+                    }
+                } else if (!mIsMuted && volume == 0) {
+                    mIsMuted = true;
+                    if (mEnabled) {
+                        setStatus(false);
+                    }
+                }
+                AUDIO_TRACK.setVolume(volume);
                 break;
             case MSG_SET_AUDIO_TRACK:
-                boolean enabled = (Integer) message == 1;
-                if (enabled == AUDIO_TRACK.isEnabled()) {
-                    return;
-                }
-                if (!enabled) {
-                    // mAudioClock can be different from getPositionUs. In order to sync them,
-                    // we set mAudioClock.
-                    mAudioClock.setPositionUs(getPositionUs());
-                }
-                AUDIO_TRACK.setStatus(enabled);
-                if (enabled) {
-                    // When AUDIO_TRACK is enabled, we need to clear AUDIO_TRACK and seek to
-                    // the current position. If not, AUDIO_TRACK has the obsolete data.
-                    seekTo(mAudioClock.getPositionUs());
-                }
+                mEnabled = (Integer) message == 1;
+                setStatus(mEnabled);
                 break;
             case MSG_SET_PLAYBACK_SPEED:
                 mAudioClock.setPlaybackSpeed((Float) message);
@@ -537,4 +715,21 @@
                 super.handleMessage(messageType, message);
         }
     }
+
+    private void setStatus(boolean enabled) {
+        if (enabled == AUDIO_TRACK.isEnabled()) {
+            return;
+        }
+        if (!enabled) {
+            // mAudioClock can be different from getPositionUs. In order to sync them,
+            // we set mAudioClock.
+            mAudioClock.setPositionUs(getPositionUs());
+        }
+        AUDIO_TRACK.setStatus(enabled);
+        if (enabled) {
+            // When AUDIO_TRACK is enabled, we need to clear AUDIO_TRACK and seek to
+            // the current position. If not, AUDIO_TRACK has the obsolete data.
+            seekTo(mAudioClock.getPositionUs());
+        }
+    }
 }
diff --git a/src/com/android/tv/tuner/exoplayer/ac3/Ac3TrackRenderer.java b/src/com/android/tv/tuner/exoplayer/audio/MpegTsMediaCodecAudioTrackRenderer.java
similarity index 81%
rename from src/com/android/tv/tuner/exoplayer/ac3/Ac3TrackRenderer.java
rename to src/com/android/tv/tuner/exoplayer/audio/MpegTsMediaCodecAudioTrackRenderer.java
index 2bf86b5..142aa9b 100644
--- a/src/com/android/tv/tuner/exoplayer/ac3/Ac3TrackRenderer.java
+++ b/src/com/android/tv/tuner/exoplayer/audio/MpegTsMediaCodecAudioTrackRenderer.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.exoplayer.ac3;
+package com.android.tv.tuner.exoplayer.audio;
 
 import android.os.Handler;
 
@@ -25,16 +25,13 @@
 
 /**
  * MPEG-2 TS audio track renderer.
- * <p>Since the audio output from {@link android.media.MediaExtractor} contains extra samples at
- * the beginning, using original {@link MediaCodecAudioTrackRenderer} as audio renderer causes
- * asynchronous Audio/Video outputs.
- * This class calculates the offset of audio data and adjust the presentation times to avoid the
- * asynchronous Audio/Video problem.
+ *
+ * <p>Since the audio output from {@link android.media.MediaExtractor} contains extra samples at the
+ * beginning, using original {@link MediaCodecAudioTrackRenderer} as audio renderer causes
+ * asynchronous Audio/Video outputs. This class calculates the offset of audio data and adjust the
+ * presentation times to avoid the asynchronous Audio/Video problem.
  */
-public class Ac3TrackRenderer extends MediaCodecAudioTrackRenderer {
-    private final String TAG = "Ac3TrackRenderer";
-    private final boolean DEBUG = false;
-
+public class MpegTsMediaCodecAudioTrackRenderer extends MediaCodecAudioTrackRenderer {
     private final Ac3EventListener mListener;
 
     public interface Ac3EventListener extends EventListener {
@@ -47,8 +44,11 @@
         void onAudioTrackSetPlaybackParamsError(IllegalArgumentException e);
     }
 
-    public Ac3TrackRenderer(SampleSource source, MediaCodecSelector mediaCodecSelector,
-            Handler eventHandler, EventListener eventListener) {
+    public MpegTsMediaCodecAudioTrackRenderer(
+            SampleSource source,
+            MediaCodecSelector mediaCodecSelector,
+            Handler eventHandler,
+            EventListener eventListener) {
         super(source, mediaCodecSelector, eventHandler, eventListener);
         mListener = (Ac3EventListener) eventListener;
     }
diff --git a/src/com/android/tv/tuner/exoplayer/buffer/BufferManager.java b/src/com/android/tv/tuner/exoplayer/buffer/BufferManager.java
index eb596e9..112e9dc 100644
--- a/src/com/android/tv/tuner/exoplayer/buffer/BufferManager.java
+++ b/src/com/android/tv/tuner/exoplayer/buffer/BufferManager.java
@@ -25,13 +25,14 @@
 import android.util.Pair;
 
 import com.google.android.exoplayer.SampleHolder;
+import com.android.tv.common.SoftPreconditions;
 import com.android.tv.tuner.exoplayer.SampleExtractor;
 import com.android.tv.util.Utils;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
@@ -59,7 +60,8 @@
 
     private final SampleChunk.SampleChunkCreator mSampleChunkCreator;
     // Maps from track name to a map which maps from starting position to {@link SampleChunk}.
-    private final Map<String, SortedMap<Long, SampleChunk>> mChunkMap = new ArrayMap<>();
+    private final Map<String, SortedMap<Long, Pair<SampleChunk, Integer>>> mChunkMap =
+            new ArrayMap<>();
     private final Map<String, Long> mStartPositionMap = new ArrayMap<>();
     private final Map<String, ChunkEvictedListener> mEvictListeners = new ArrayMap<>();
     private final StorageManager mStorageManager;
@@ -77,13 +79,11 @@
         }
     };
 
-    private volatile boolean mClosed = false;
     private int mMinSampleSizeForSpeedCheck = MINIMUM_SAMPLE_SIZE_FOR_SPEED_CHECK;
     private long mTotalWriteSize;
     private long mTotalWriteTimeNs;
     private float mWriteBandwidth = 0.0f;
     private volatile int mSpeedCheckCount;
-    private boolean mDisabled = false;
 
     public interface ChunkEvictedListener {
         void onChunkEvicted(String id, long createdTimeMs);
@@ -174,6 +174,66 @@
     }
 
     /**
+     * A Track format which will be loaded and saved from the permanent storage for recordings.
+     */
+    public static class TrackFormat {
+
+        /**
+         * The track id for the specified track. The track id will be used as a track identifier
+         * for recordings.
+         */
+        public final String trackId;
+
+        /**
+         * The {@link MediaFormat} for the specified track.
+         */
+        public final MediaFormat format;
+
+        /**
+         * Creates TrackFormat.
+         * @param trackId
+         * @param format
+         */
+        public TrackFormat(String trackId, MediaFormat format) {
+            this.trackId = trackId;
+            this.format = format;
+        }
+    }
+
+    /**
+     * A Holder for a sample position which will be loaded from the index file for recordings.
+     */
+    public static class PositionHolder {
+
+        /**
+         * The current sample position in microseconds.
+         * The position is identical to the PTS(presentation time stamp) of the sample.
+         */
+        public final long positionUs;
+
+        /**
+         * Base sample position for the current {@link SampleChunk}.
+         */
+        public final long basePositionUs;
+
+        /**
+         * The file offset for the current sample in the current {@link SampleChunk}.
+         */
+        public final int offset;
+
+        /**
+         * Creates a holder for a specific position in the recording.
+         * @param positionUs
+         * @param offset
+         */
+        public PositionHolder(long positionUs, long basePositionUs, int offset) {
+            this.positionUs = positionUs;
+            this.basePositionUs = basePositionUs;
+            this.offset = offset;
+        }
+    }
+
+    /**
      * Storage configuration and policy manager for {@link BufferManager}
      */
     public interface StorageManager {
@@ -186,11 +246,6 @@
         File getBufferDir();
 
         /**
-         * Cleans up storage.
-         */
-        void clearStorage();
-
-        /**
          * Informs whether the storage is used for persistent use. (eg. dvr recording/play)
          *
          * @return {@code true} if stored files are persistent
@@ -220,29 +275,27 @@
          * Reads track name & {@link MediaFormat} from storage.
          *
          * @param isAudio {@code true} if it is for audio track
-         * @return {@link Pair} of track name & {@link MediaFormat}
-         * @throws IOException
+         * @return {@link List} of TrackFormat
          */
-        Pair<String, MediaFormat> readTrackInfoFile(boolean isAudio) throws IOException;
+        List<TrackFormat> readTrackInfoFiles(boolean isAudio);
 
         /**
-         * Reads sample indexes for each written sample from storage.
+         * Reads key sample positions for each written sample from storage.
          *
          * @param trackId track name
          * @return indexes of the specified track
          * @throws IOException
          */
-        ArrayList<Long> readIndexFile(String trackId) throws IOException;
+        ArrayList<PositionHolder> readIndexFile(String trackId) throws IOException;
 
         /**
          * Writes track information to storage.
          *
-         * @param trackId track name
-         * @param format {@link android.media.MediaFormat} of the track
+         * @param formatList {@list List} of TrackFormat
          * @param isAudio {@code true} if it is for audio track
          * @throws IOException
          */
-        void writeTrackInfoFile(String trackId, MediaFormat format, boolean isAudio)
+        void writeTrackInfoFiles(List<TrackFormat> formatList, boolean isAudio)
                 throws IOException;
 
         /**
@@ -252,7 +305,7 @@
          * @param index {@link SampleChunk} container
          * @throws IOException
          */
-        void writeIndexFile(String trackName, SortedMap<Long, SampleChunk> index)
+        void writeIndexFile(String trackName, SortedMap<Long, Pair<SampleChunk, Integer>> index)
                 throws IOException;
     }
 
@@ -307,7 +360,6 @@
             SampleChunk.SampleChunkCreator sampleChunkCreator) {
         mStorageManager = storageManager;
         mSampleChunkCreator = sampleChunkCreator;
-        clearBuffer(true);
     }
 
     public void registerChunkEvictedListener(String id, ChunkEvictedListener listener) {
@@ -318,44 +370,44 @@
         mEvictListeners.remove(id);
     }
 
-    private void clearBuffer(boolean deleteFiles) {
-        mChunkMap.clear();
-        if (deleteFiles) {
-            mStorageManager.clearStorage();
-        }
-        mBufferSize = 0;
-    }
-
     private static String getFileName(String id, long positionUs) {
         return String.format(Locale.ENGLISH, "%s_%016x.chunk", id, positionUs);
     }
 
     /**
-     * Creates a new {@link SampleChunk} for caching samples.
+     * Creates a new {@link SampleChunk} for caching samples if it is needed.
      *
      * @param id the name of the track
-     * @param positionUs starting position of the {@link SampleChunk} in micro seconds.
+     * @param positionUs current position to write a sample in micro seconds.
      * @param samplePool {@link SamplePool} for the fast creation of samples.
+     * @param currentChunk the current {@link SampleChunk} to write, {@code null} when to create
+     *                     a new {@link SampleChunk}.
+     * @param currentOffset the current offset to write.
      * @return returns the created {@link SampleChunk}.
      * @throws IOException
      */
-    public SampleChunk createNewWriteFile(String id, long positionUs,
-            SamplePool samplePool) throws IOException {
+    public SampleChunk createNewWriteFileIfNeeded(String id, long positionUs, SamplePool samplePool,
+            SampleChunk currentChunk, int currentOffset) throws IOException {
         if (!maybeEvictChunk()) {
             throw new IOException("Not enough storage space");
         }
-        SortedMap<Long, SampleChunk> map = mChunkMap.get(id);
+        SortedMap<Long, Pair<SampleChunk, Integer>> map = mChunkMap.get(id);
         if (map == null) {
             map = new TreeMap<>();
             mChunkMap.put(id, map);
             mStartPositionMap.put(id, positionUs);
             mPendingDelete.init(id);
         }
-        File file = new File(mStorageManager.getBufferDir(), getFileName(id, positionUs));
-        SampleChunk sampleChunk = mSampleChunkCreator.createSampleChunk(samplePool, file,
-                positionUs, mChunkCallback);
-        map.put(positionUs, sampleChunk);
-        return sampleChunk;
+        if (currentChunk == null) {
+            File file = new File(mStorageManager.getBufferDir(), getFileName(id, positionUs));
+            SampleChunk sampleChunk = mSampleChunkCreator
+                    .createSampleChunk(samplePool, file, positionUs, mChunkCallback);
+            map.put(positionUs, new Pair(sampleChunk, 0));
+            return sampleChunk;
+        } else {
+            map.put(positionUs, new Pair(currentChunk, currentOffset));
+            return null;
+        }
     }
 
     /**
@@ -366,10 +418,10 @@
      * @throws IOException
      */
     public void loadTrackFromStorage(String trackId, SamplePool samplePool) throws IOException {
-        ArrayList<Long> keyPositions = mStorageManager.readIndexFile(trackId);
-        long startPositionUs = keyPositions.size() > 0 ? keyPositions.get(0) : 0;
+        ArrayList<PositionHolder> keyPositions = mStorageManager.readIndexFile(trackId);
+        long startPositionUs = keyPositions.size() > 0 ? keyPositions.get(0).positionUs : 0;
 
-        SortedMap<Long, SampleChunk> map = mChunkMap.get(trackId);
+        SortedMap<Long, Pair<SampleChunk, Integer>> map = mChunkMap.get(trackId);
         if (map == null) {
             map = new TreeMap<>();
             mChunkMap.put(trackId, map);
@@ -377,11 +429,15 @@
             mPendingDelete.init(trackId);
         }
         SampleChunk chunk = null;
-        for (long positionUs: keyPositions) {
-            chunk = mSampleChunkCreator.loadSampleChunkFromFile(samplePool,
-                    mStorageManager.getBufferDir(), getFileName(trackId, positionUs), positionUs,
-                    mChunkCallback, chunk);
-            map.put(positionUs, chunk);
+        long basePositionUs = -1;
+        for (PositionHolder position: keyPositions) {
+            if (position.basePositionUs != basePositionUs) {
+                chunk = mSampleChunkCreator.loadSampleChunkFromFile(samplePool,
+                        mStorageManager.getBufferDir(), getFileName(trackId, position.positionUs),
+                        position.positionUs, mChunkCallback, chunk);
+                basePositionUs = position.basePositionUs;
+            }
+            map.put(position.positionUs, new Pair(chunk, position.offset));
         }
     }
 
@@ -392,19 +448,19 @@
      * @param positionUs the position.
      * @return returns the found {@link SampleChunk}.
      */
-    public SampleChunk getReadFile(String id, long positionUs) {
-        SortedMap<Long, SampleChunk> map = mChunkMap.get(id);
+    public Pair<SampleChunk, Integer> getReadFile(String id, long positionUs) {
+        SortedMap<Long, Pair<SampleChunk, Integer>> map = mChunkMap.get(id);
         if (map == null) {
             return null;
         }
-        SampleChunk sampleChunk;
-        SortedMap<Long, SampleChunk> headMap = map.headMap(positionUs + 1);
+        Pair<SampleChunk, Integer> ret;
+        SortedMap<Long, Pair<SampleChunk, Integer>> headMap = map.headMap(positionUs + 1);
         if (!headMap.isEmpty()) {
-            sampleChunk = headMap.get(headMap.lastKey());
+            ret = headMap.get(headMap.lastKey());
         } else {
-            sampleChunk = map.get(map.firstKey());
+            ret = map.get(map.firstKey());
         }
-        return sampleChunk;
+        return ret;
     }
 
     /**
@@ -439,15 +495,16 @@
                 // Since chunks are persistent, we cannot evict chunks.
                 return false;
             }
-            SortedMap<Long, SampleChunk> earliestChunkMap = null;
+            SortedMap<Long, Pair<SampleChunk, Integer>> earliestChunkMap = null;
             SampleChunk earliestChunk = null;
             String earliestChunkId = null;
-            for (Map.Entry<String, SortedMap<Long, SampleChunk>> entry : mChunkMap.entrySet()) {
-                SortedMap<Long, SampleChunk> map = entry.getValue();
+            for (Map.Entry<String, SortedMap<Long, Pair<SampleChunk, Integer>>> entry :
+                    mChunkMap.entrySet()) {
+                SortedMap<Long, Pair<SampleChunk, Integer>> map = entry.getValue();
                 if (map.isEmpty()) {
                     continue;
                 }
-                SampleChunk chunk = map.get(map.firstKey());
+                SampleChunk chunk = map.get(map.firstKey()).first;
                 if (earliestChunk == null
                         || chunk.getCreatedTimeMs() < earliestChunk.getCreatedTimeMs()) {
                     earliestChunkMap = map;
@@ -473,8 +530,9 @@
             }
             pendingDelete = mPendingDelete.getSize();
         }
-        for (Map.Entry<String, SortedMap<Long, SampleChunk>> entry : mChunkMap.entrySet()) {
-            SortedMap<Long, SampleChunk> map = entry.getValue();
+        for (Map.Entry<String, SortedMap<Long, Pair<SampleChunk, Integer>>> entry :
+                mChunkMap.entrySet()) {
+            SortedMap<Long, Pair<SampleChunk, Integer>> map = entry.getValue();
             if (map.isEmpty()) {
                 continue;
             }
@@ -489,70 +547,74 @@
      * @return returns all track information which is found by {@link BufferManager.StorageManager}.
      * @throws IOException
      */
-    public ArrayList<Pair<String, MediaFormat>> readTrackInfoFiles() throws IOException {
-        ArrayList<Pair<String, MediaFormat>> trackInfos = new ArrayList<>();
-        try {
-            trackInfos.add(mStorageManager.readTrackInfoFile(false));
-        } catch (FileNotFoundException e) {
-            // There can be a single track only recording. (eg. audio-only, video-only)
-            // So the exception should not stop the read.
+    public List<TrackFormat> readTrackInfoFiles() throws IOException {
+        List<TrackFormat> trackFormatList = new ArrayList<>();
+        trackFormatList.addAll(mStorageManager.readTrackInfoFiles(false));
+        trackFormatList.addAll(mStorageManager.readTrackInfoFiles(true));
+        if (trackFormatList.isEmpty()) {
+            throw new IOException("No track information to load");
         }
-        try {
-            trackInfos.add(mStorageManager.readTrackInfoFile(true));
-        } catch (FileNotFoundException e) {
-            // See above catch block.
-        }
-        return trackInfos;
+        return trackFormatList;
     }
 
     /**
      * Writes track information and index information for all tracks.
      *
-     * @param audio audio information.
-     * @param video video information.
+     * @param audios list of audio track information
+     * @param videos list of audio track information
      * @throws IOException
      */
-    public void writeMetaFiles(Pair<String, MediaFormat> audio, Pair<String, MediaFormat> video)
+    public void writeMetaFiles(List<TrackFormat> audios, List<TrackFormat> videos)
             throws IOException {
-        if (audio != null) {
-            mStorageManager.writeTrackInfoFile(audio.first, audio.second, true);
-            SortedMap<Long, SampleChunk> map = mChunkMap.get(audio.first);
-            if (map == null) {
-                throw new IOException("Audio track index missing");
-            }
-            mStorageManager.writeIndexFile(audio.first, map);
+        if (audios.isEmpty() && videos.isEmpty()) {
+            throw new IOException("No track information to save");
         }
-        if (video != null) {
-            mStorageManager.writeTrackInfoFile(video.first, video.second, false);
-            SortedMap<Long, SampleChunk> map = mChunkMap.get(video.first);
-            if (map == null) {
-                throw new IOException("Video track index missing");
+        if (!audios.isEmpty()) {
+            mStorageManager.writeTrackInfoFiles(audios, true);
+            for (TrackFormat trackFormat : audios) {
+                SortedMap<Long, Pair<SampleChunk, Integer>> map =
+                        mChunkMap.get(trackFormat.trackId);
+                if (map == null) {
+                    throw new IOException("Audio track index missing");
+                }
+                mStorageManager.writeIndexFile(trackFormat.trackId, map);
             }
-            mStorageManager.writeIndexFile(video.first, map);
         }
-    }
-
-    /**
-     * Marks it is closed and it is not used anymore.
-     */
-    public void close() {
-        // Clean-up may happen after this is called.
-        mClosed = true;
+        if (!videos.isEmpty()) {
+            mStorageManager.writeTrackInfoFiles(videos, false);
+            for (TrackFormat trackFormat : videos) {
+                SortedMap<Long, Pair<SampleChunk, Integer>> map =
+                        mChunkMap.get(trackFormat.trackId);
+                if (map == null) {
+                    throw new IOException("Video track index missing");
+                }
+                mStorageManager.writeIndexFile(trackFormat.trackId, map);
+            }
+        }
     }
 
     /**
      * Releases all the resources.
      */
     public void release() {
-        mPendingDelete.release();
-        for (Map.Entry<String, SortedMap<Long, SampleChunk>> entry : mChunkMap.entrySet()) {
-            for (SampleChunk chunk : entry.getValue().values()) {
-                SampleChunk.IoState.release(chunk, !mStorageManager.isPersistent());
+        try {
+            mPendingDelete.release();
+            for (Map.Entry<String, SortedMap<Long, Pair<SampleChunk, Integer>>> entry :
+                    mChunkMap.entrySet()) {
+                SampleChunk toRelease = null;
+                for (Pair<SampleChunk, Integer> positions : entry.getValue().values()) {
+                    if (toRelease != positions.first) {
+                        toRelease = positions.first;
+                        SampleChunk.IoState.release(toRelease, !mStorageManager.isPersistent());
+                    }
+                }
             }
-        }
-        mChunkMap.clear();
-        if (mClosed) {
-            clearBuffer(!mStorageManager.isPersistent());
+            mChunkMap.clear();
+        } catch (ConcurrentModificationException | NullPointerException e) {
+            // TODO: remove this after it it confirmed that race condition issues are resolved.
+            // b/32492258, b/32373376
+            SoftPreconditions.checkState(false, "Exception on BufferManager#release: ",
+                    e.toString());
         }
     }
 
@@ -611,20 +673,6 @@
     }
 
     /**
-     * Marks {@link BufferManager} object disabled to prevent it from the future use.
-     */
-    public void disable() {
-        mDisabled = true;
-    }
-
-    /**
-     * Returns if {@link BufferManager} object is disabled.
-     */
-    public boolean isDisabled() {
-        return mDisabled;
-    }
-
-    /**
      * Returns if {@link BufferManager} has checked the write speed,
      * which is suitable for Trickplay.
      */
diff --git a/src/com/android/tv/tuner/exoplayer/buffer/DvrStorageManager.java b/src/com/android/tv/tuner/exoplayer/buffer/DvrStorageManager.java
index 6a0502a..6a09016 100644
--- a/src/com/android/tv/tuner/exoplayer/buffer/DvrStorageManager.java
+++ b/src/com/android/tv/tuner/exoplayer/buffer/DvrStorageManager.java
@@ -17,8 +17,12 @@
 package com.android.tv.tuner.exoplayer.buffer;
 
 import android.media.MediaFormat;
+import android.util.Log;
 import android.util.Pair;
 
+import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
+import com.google.protobuf.nano.MessageNano;
+
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
 import java.io.File;
@@ -28,18 +32,25 @@
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.SortedMap;
 
 /**
  * Manages DVR storage.
  */
 public class DvrStorageManager implements BufferManager.StorageManager {
+    private static final String TAG = "DvrStorageManager";
 
     // TODO: make serializable classes and use protobuf after internal data structure is finalized.
     private static final String KEY_PIXEL_WIDTH_HEIGHT_RATIO =
             "com.google.android.videos.pixelWidthHeightRatio";
+    private static final String META_FILE_TYPE_AUDIO = "audio";
+    private static final String META_FILE_TYPE_VIDEO = "video";
+    private static final String META_FILE_TYPE_CAPTION = "caption";
     private static final String META_FILE_SUFFIX = ".meta";
     private static final String IDX_FILE_SUFFIX = ".idx";
+    private static final String IDX_FILE_SUFFIX_V2 = IDX_FILE_SUFFIX + "2";
 
     // Size of minimum reserved storage buffer which will be used to save meta files
     // and index files after actual recording finished.
@@ -59,18 +70,6 @@
     }
 
     @Override
-    public void clearStorage() {
-        if (mIsRecording) {
-            File[] files = mBufferDir.listFiles();
-            if (files != null && files.length > 0) {
-                for (File file : files) {
-                    file.delete();
-                }
-            }
-        }
-    }
-
-    @Override
     public File getBufferDir() {
         return mBufferDir;
     }
@@ -132,6 +131,17 @@
         }
     }
 
+    private void readFormatStringOptional(DataInputStream in, MediaFormat format, String key) {
+        try {
+            String str = readString(in);
+            if (str != null) {
+                format.setString(key, str);
+            }
+        } catch (IOException e) {
+            // Since we are reading optional field, ignore the exception.
+        }
+    }
+
     private ByteBuffer readByteBuffer(DataInputStream in) throws IOException {
         int len = in.readInt();
         if (len <= 0) {
@@ -155,36 +165,101 @@
     }
 
     @Override
-    public Pair<String, MediaFormat> readTrackInfoFile(boolean isAudio) throws IOException {
-        File file = new File(getBufferDir(), (isAudio ? "audio" : "video") + META_FILE_SUFFIX);
-        try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
-            String name = readString(in);
-            MediaFormat format = new MediaFormat();
-            readFormatString(in, format, MediaFormat.KEY_MIME);
-            readFormatInt(in, format, MediaFormat.KEY_MAX_INPUT_SIZE);
-            readFormatInt(in, format, MediaFormat.KEY_WIDTH);
-            readFormatInt(in, format, MediaFormat.KEY_HEIGHT);
-            readFormatInt(in, format, MediaFormat.KEY_CHANNEL_COUNT);
-            readFormatInt(in, format, MediaFormat.KEY_SAMPLE_RATE);
-            readFormatFloat(in, format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
-            for (int i = 0; i < 3; ++i) {
-                readFormatByteBuffer(in, format, "csd-" + i);
+    public List<BufferManager.TrackFormat> readTrackInfoFiles(boolean isAudio) {
+        List<BufferManager.TrackFormat> trackFormatList = new ArrayList<>();
+        int index = 0;
+        boolean trackNotFound = false;
+        do {
+            String fileName = (isAudio ? META_FILE_TYPE_AUDIO : META_FILE_TYPE_VIDEO)
+                    + ((index == 0) ? META_FILE_SUFFIX : (index + META_FILE_SUFFIX));
+            File file = new File(getBufferDir(), fileName);
+            try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
+                String name = readString(in);
+                MediaFormat format = new MediaFormat();
+                readFormatString(in, format, MediaFormat.KEY_MIME);
+                readFormatInt(in, format, MediaFormat.KEY_MAX_INPUT_SIZE);
+                readFormatInt(in, format, MediaFormat.KEY_WIDTH);
+                readFormatInt(in, format, MediaFormat.KEY_HEIGHT);
+                readFormatInt(in, format, MediaFormat.KEY_CHANNEL_COUNT);
+                readFormatInt(in, format, MediaFormat.KEY_SAMPLE_RATE);
+                readFormatFloat(in, format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
+                for (int i = 0; i < 3; ++i) {
+                    readFormatByteBuffer(in, format, "csd-" + i);
+                }
+                readFormatLong(in, format, MediaFormat.KEY_DURATION);
+
+                // This is optional since language field is added later.
+                readFormatStringOptional(in, format, MediaFormat.KEY_LANGUAGE);
+                trackFormatList.add(new BufferManager.TrackFormat(name, format));
+            } catch (IOException e) {
+                trackNotFound = true;
             }
-            readFormatLong(in, format, MediaFormat.KEY_DURATION);
-            return new Pair<>(name, format);
+            index++;
+        } while(!trackNotFound);
+        return trackFormatList;
+    }
+
+    /**
+     * Reads caption information from files.
+     *
+     * @return a list of {@link AtscCaptionTrack} objects which store caption information.
+     */
+    public List<AtscCaptionTrack> readCaptionInfoFiles() {
+        List<AtscCaptionTrack> tracks = new ArrayList<>();
+        int index = 0;
+        boolean trackNotFound = false;
+        do {
+            String fileName = META_FILE_TYPE_CAPTION +
+                    ((index == 0) ? META_FILE_SUFFIX : (index + META_FILE_SUFFIX));
+            File file = new File(getBufferDir(), fileName);
+            try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
+                byte[] data = new byte[(int) file.length()];
+                in.read(data);
+                tracks.add(AtscCaptionTrack.parseFrom(data));
+            } catch (IOException e) {
+                trackNotFound = true;
+            }
+            index++;
+        } while(!trackNotFound);
+        return tracks;
+    }
+
+    private ArrayList<BufferManager.PositionHolder> readOldIndexFile(File indexFile)
+            throws IOException {
+        ArrayList<BufferManager.PositionHolder> indices = new ArrayList<>();
+        try (DataInputStream in = new DataInputStream(new FileInputStream(indexFile))) {
+            long count = in.readLong();
+            for (long i = 0; i < count; ++i) {
+                long positionUs = in.readLong();
+                indices.add(new BufferManager.PositionHolder(positionUs, positionUs, 0));
+            }
+            return indices;
+        }
+    }
+
+    private ArrayList<BufferManager.PositionHolder> readNewIndexFile(File indexFile)
+            throws IOException {
+        ArrayList<BufferManager.PositionHolder> indices = new ArrayList<>();
+        try (DataInputStream in = new DataInputStream(new FileInputStream(indexFile))) {
+            long count = in.readLong();
+            for (long i = 0; i < count; ++i) {
+                long positionUs = in.readLong();
+                long basePositionUs = in.readLong();
+                int offset = in.readInt();
+                indices.add(new BufferManager.PositionHolder(positionUs, basePositionUs, offset));
+            }
+            return indices;
         }
     }
 
     @Override
-    public ArrayList<Long> readIndexFile(String trackId) throws IOException {
-        ArrayList<Long> indices = new ArrayList<>();
-        File file = new File(getBufferDir(), trackId + IDX_FILE_SUFFIX);
-        try (DataInputStream in = new DataInputStream(new FileInputStream(file))) {
-            long count = in.readLong();
-            for (long i = 0; i < count; ++i) {
-                indices.add(in.readLong());
-            }
-            return indices;
+    public ArrayList<BufferManager.PositionHolder> readIndexFile(String trackId)
+            throws IOException {
+        File file = new File(getBufferDir(), trackId + IDX_FILE_SUFFIX_V2);
+        if (file.exists()) {
+            return readNewIndexFile(file);
+        } else {
+            return readOldIndexFile(new File(getBufferDir(),trackId + IDX_FILE_SUFFIX));
         }
     }
 
@@ -254,33 +329,63 @@
     }
 
     @Override
-    public void writeTrackInfoFile(String trackId, MediaFormat format, boolean isAudio)
+    public void writeTrackInfoFiles(List<BufferManager.TrackFormat> formatList, boolean isAudio)
             throws IOException {
-        File file = new File(getBufferDir(), (isAudio ? "audio" : "video") + META_FILE_SUFFIX);
-        try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
-            writeString(out, trackId);
-            writeFormatString(out, format, MediaFormat.KEY_MIME);
-            writeFormatInt(out, format, MediaFormat.KEY_MAX_INPUT_SIZE);
-            writeFormatInt(out, format, MediaFormat.KEY_WIDTH);
-            writeFormatInt(out, format, MediaFormat.KEY_HEIGHT);
-            writeFormatInt(out, format, MediaFormat.KEY_CHANNEL_COUNT);
-            writeFormatInt(out, format, MediaFormat.KEY_SAMPLE_RATE);
-            writeFormatFloat(out, format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
-            for (int i = 0; i < 3; ++i) {
-                writeFormatByteBuffer(out, format, "csd-" + i);
+        for (int i = 0; i < formatList.size() ; ++i) {
+            BufferManager.TrackFormat trackFormat = formatList.get(i);
+            String fileName = (isAudio ? META_FILE_TYPE_AUDIO : META_FILE_TYPE_VIDEO)
+                    + ((i == 0) ? META_FILE_SUFFIX : (i + META_FILE_SUFFIX));
+            File file = new File(getBufferDir(), fileName);
+            try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
+                writeString(out, trackFormat.trackId);
+                writeFormatString(out, trackFormat.format, MediaFormat.KEY_MIME);
+                writeFormatInt(out, trackFormat.format, MediaFormat.KEY_MAX_INPUT_SIZE);
+                writeFormatInt(out, trackFormat.format, MediaFormat.KEY_WIDTH);
+                writeFormatInt(out, trackFormat.format, MediaFormat.KEY_HEIGHT);
+                writeFormatInt(out, trackFormat.format, MediaFormat.KEY_CHANNEL_COUNT);
+                writeFormatInt(out, trackFormat.format, MediaFormat.KEY_SAMPLE_RATE);
+                writeFormatFloat(out, trackFormat.format, KEY_PIXEL_WIDTH_HEIGHT_RATIO);
+                for (int j = 0; j < 3; ++j) {
+                    writeFormatByteBuffer(out, trackFormat.format, "csd-" + j);
+                }
+                writeFormatLong(out, trackFormat.format, MediaFormat.KEY_DURATION);
+                writeFormatString(out, trackFormat.format, MediaFormat.KEY_LANGUAGE);
             }
-            writeFormatLong(out, format, MediaFormat.KEY_DURATION);
+        }
+    }
+
+    /**
+     * Writes caption information to files.
+     *
+     * @param tracks a list of {@link AtscCaptionTrack} objects which store caption information.
+     */
+    public void writeCaptionInfoFiles(List<AtscCaptionTrack> tracks) {
+        if (tracks == null || tracks.isEmpty()) {
+            return;
+        }
+        for (int i = 0; i < tracks.size(); i++) {
+            AtscCaptionTrack track = tracks.get(i);
+            String fileName = META_FILE_TYPE_CAPTION +
+                    ((i == 0) ? META_FILE_SUFFIX : (i + META_FILE_SUFFIX));
+            File file = new File(getBufferDir(), fileName);
+            try (DataOutputStream out = new DataOutputStream(new FileOutputStream(file))) {
+                out.write(MessageNano.toByteArray(track));
+            } catch (Exception e) {
+                Log.e(TAG, "Fail to write caption info to files", e);
+            }
         }
     }
 
     @Override
-    public void writeIndexFile(String trackName, SortedMap<Long, SampleChunk> index)
+    public void writeIndexFile(String trackName, SortedMap<Long, Pair<SampleChunk, Integer>> index)
             throws IOException {
-        File indexFile  = new File(getBufferDir(), trackName + IDX_FILE_SUFFIX);
+        File indexFile  = new File(getBufferDir(), trackName + IDX_FILE_SUFFIX_V2);
         try (DataOutputStream out = new DataOutputStream(new FileOutputStream(indexFile))) {
             out.writeLong(index.size());
-            for (Long key : index.keySet()) {
-                out.writeLong(key);
+            for (Map.Entry<Long, Pair<SampleChunk, Integer>> entry : index.entrySet()) {
+                out.writeLong(entry.getKey());
+                out.writeLong(entry.getValue().first.getStartPositionUs());
+                out.writeInt(entry.getValue().second);
             }
         }
     }
diff --git a/src/com/android/tv/tuner/exoplayer/buffer/RecordingSampleBuffer.java b/src/com/android/tv/tuner/exoplayer/buffer/RecordingSampleBuffer.java
index 4869b49..af0c3f0 100644
--- a/src/com/android/tv/tuner/exoplayer/buffer/RecordingSampleBuffer.java
+++ b/src/com/android/tv/tuner/exoplayer/buffer/RecordingSampleBuffer.java
@@ -66,9 +66,14 @@
     public static final int BUFFER_REASON_RECORDING = 2;
 
     /**
-     * The duration of a chunk of samples, {@link SampleChunk}.
+     * The minimum duration to support seek in Trickplay.
      */
-    static final long CHUNK_DURATION_US = TimeUnit.MILLISECONDS.toMicros(500);
+    static final long MIN_SEEK_DURATION_US = TimeUnit.MILLISECONDS.toMicros(500);
+
+    /**
+     * The duration of a {@link SampleChunk} for recordings.
+     */
+    static final long RECORDING_CHUNK_DURATION_US = MIN_SEEK_DURATION_US * 1200; // 10 minutes
     private static final long BUFFER_WRITE_TIMEOUT_MS = 10 * 1000;  // 10 seconds
     private static final long BUFFER_NEEDED_US =
             1000L * Math.max(MpegTsPlayer.MIN_BUFFER_MS, MpegTsPlayer.MIN_REBUFFER_MS);
@@ -79,7 +84,6 @@
 
     private int mTrackCount;
     private boolean[] mTrackSelected;
-    private List<String> mIds;
     private List<SampleQueue> mReadSampleQueues;
     private final SamplePool mSamplePool = new SamplePool();
     private long mLastBufferedPositionUs = C.UNKNOWN_TIME_US;
@@ -130,7 +134,6 @@
         if (mTrackCount <= 0) {
             throw new IOException("No tracks to initialize");
         }
-        mIds = ids;
         mTrackSelected = new boolean[mTrackCount];
         mReadSampleQueues = new ArrayList<>();
         mSampleChunkIoHelper = new SampleChunkIoHelper(ids, mediaFormats, mBufferReason,
@@ -139,6 +142,9 @@
             mReadSampleQueues.add(i, new SampleQueue(mSamplePool));
         }
         mSampleChunkIoHelper.init();
+        for (int i = 0; i < mTrackCount; ++i) {
+            mBufferManager.registerChunkEvictedListener(ids.get(i), RecordingSampleBuffer.this);
+        }
     }
 
     @Override
@@ -146,8 +152,6 @@
         if (!mTrackSelected[index]) {
             mTrackSelected[index] = true;
             mReadSampleQueues.get(index).clear();
-            mBufferManager.registerChunkEvictedListener(mIds.get(index),
-                    RecordingSampleBuffer.this);
             mSampleChunkIoHelper.openRead(index, mCurrentPlaybackPositionUs);
         }
     }
@@ -157,7 +161,7 @@
         if (mTrackSelected[index]) {
             mTrackSelected[index] = false;
             mReadSampleQueues.get(index).clear();
-            mBufferManager.unregisterChunkEvictedListener(mIds.get(index));
+            mSampleChunkIoHelper.closeRead(index);
         }
     }
 
@@ -193,7 +197,6 @@
         }
         // Disables buffering samples afterwards, and notifies the disk speed is slow.
         Log.w(TAG, "Disk is too slow for trickplay");
-        mBufferManager.disable();
         mBufferListener.onDiskTooSlow();
     }
 
@@ -205,7 +208,7 @@
     private boolean maybeReadSample(SampleQueue queue, int index) {
         if (queue.getLastQueuedPositionUs() != null
                 && queue.getLastQueuedPositionUs() > mCurrentPlaybackPositionUs + BUFFER_NEEDED_US
-                && queue.isDurationGreaterThan(CHUNK_DURATION_US)) {
+                && queue.isDurationGreaterThan(MIN_SEEK_DURATION_US)) {
             // The speed of queuing samples can be higher than the playback speed.
             // If the duration of the samples in the queue is not limited,
             // samples can be accumulated and there can be out-of-memory issues.
@@ -300,7 +303,7 @@
     public void onChunkEvicted(String id, long createdTimeMs) {
         if (mBufferListener != null) {
             mBufferListener.onBufferStartTimeChanged(
-                    createdTimeMs + TimeUnit.MICROSECONDS.toMillis(CHUNK_DURATION_US));
+                    createdTimeMs + TimeUnit.MICROSECONDS.toMillis(MIN_SEEK_DURATION_US));
         }
     }
 }
diff --git a/src/com/android/tv/tuner/exoplayer/buffer/SampleChunk.java b/src/com/android/tv/tuner/exoplayer/buffer/SampleChunk.java
index 552caae..04b5a07 100644
--- a/src/com/android/tv/tuner/exoplayer/buffer/SampleChunk.java
+++ b/src/com/android/tv/tuner/exoplayer/buffer/SampleChunk.java
@@ -78,7 +78,6 @@
     /**
      * A class for SampleChunk creation.
      */
-    @VisibleForTesting
     public static class SampleChunkCreator {
 
         /**
@@ -151,18 +150,23 @@
             mCurrentOffset = 0;
         }
 
+        private void reset(SampleChunk chunk, long offset) {
+            mChunk = chunk;
+            mCurrentOffset = offset;
+        }
+
         /**
          * Prepares for read I/O operation from a new SampleChunk.
          *
          * @param chunk the new SampleChunk to read from
          * @throws IOException
          */
-        void openRead(SampleChunk chunk) throws IOException {
+        void openRead(SampleChunk chunk, long offset) throws IOException {
             if (mChunk != null) {
                 mChunk.closeRead();
             }
             chunk.openRead();
-            reset(chunk);
+            reset(chunk, offset);
         }
 
         /**
@@ -241,6 +245,20 @@
         }
 
         /**
+         * Returns the current SampleChunk for subsequent I/O operation.
+         */
+        SampleChunk getChunk() {
+            return mChunk;
+        }
+
+        /**
+         * Returns the current offset of the current SampleChunk for subsequent I/O operation.
+         */
+        long getOffset() {
+            return mCurrentOffset;
+        }
+
+        /**
          * Releases SampleChunk. the SampleChunk will not be used anymore.
          *
          * @param chunk to release
diff --git a/src/com/android/tv/tuner/exoplayer/buffer/SampleChunkIoHelper.java b/src/com/android/tv/tuner/exoplayer/buffer/SampleChunkIoHelper.java
index 37ae402..ca97a91 100644
--- a/src/com/android/tv/tuner/exoplayer/buffer/SampleChunkIoHelper.java
+++ b/src/com/android/tv/tuner/exoplayer/buffer/SampleChunkIoHelper.java
@@ -21,6 +21,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
 
@@ -31,7 +32,9 @@
 import com.android.tv.tuner.exoplayer.buffer.RecordingSampleBuffer.BufferReason;
 
 import java.io.IOException;
+import java.util.LinkedList;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.ConcurrentLinkedQueue;
 
 /**
@@ -46,11 +49,13 @@
 
     private static final int MSG_OPEN_READ = 1;
     private static final int MSG_OPEN_WRITE = 2;
-    private static final int MSG_CLOSE_WRITE = 3;
-    private static final int MSG_READ = 4;
-    private static final int MSG_WRITE = 5;
-    private static final int MSG_RELEASE = 6;
+    private static final int MSG_CLOSE_READ = 3;
+    private static final int MSG_CLOSE_WRITE = 4;
+    private static final int MSG_READ = 5;
+    private static final int MSG_WRITE = 6;
+    private static final int MSG_RELEASE = 7;
 
+    private final long mSampleChunkDurationUs;
     private final int mTrackCount;
     private final List<String> mIds;
     private final List<MediaFormat> mMediaFormats;
@@ -62,9 +67,11 @@
     private Handler mIoHandler;
     private final ConcurrentLinkedQueue<SampleHolder> mReadSampleBuffers[];
     private final ConcurrentLinkedQueue<SampleHolder> mHandlerReadSampleBuffers[];
-    private final long[] mWriteEndPositionUs;
+    private final long[] mWriteIndexEndPositionUs;
+    private final long[] mWriteChunkEndPositionUs;
     private final SampleChunk.IoState[] mReadIoStates;
     private final SampleChunk.IoState[] mWriteIoStates;
+    private final Set<Integer> mSelectedTracks = new ArraySet<>();
     private long mBufferDurationUs = 0;
     private boolean mWriteEnded;
     private boolean mErrorNotified;
@@ -129,11 +136,20 @@
 
         mReadSampleBuffers = new ConcurrentLinkedQueue[mTrackCount];
         mHandlerReadSampleBuffers = new ConcurrentLinkedQueue[mTrackCount];
-        mWriteEndPositionUs = new long[mTrackCount];
+        mWriteIndexEndPositionUs = new long[mTrackCount];
+        mWriteChunkEndPositionUs = new long[mTrackCount];
         mReadIoStates = new SampleChunk.IoState[mTrackCount];
         mWriteIoStates = new SampleChunk.IoState[mTrackCount];
+
+        // Small chunk duration for live playback will give more fine grained storage usage
+        // and eviction handling for trickplay.
+        mSampleChunkDurationUs =
+                bufferReason == RecordingSampleBuffer.BUFFER_REASON_LIVE_PLAYBACK ?
+                        RecordingSampleBuffer.MIN_SEEK_DURATION_US :
+                        RecordingSampleBuffer.RECORDING_CHUNK_DURATION_US;
         for (int i = 0; i < mTrackCount; ++i) {
-            mWriteEndPositionUs[i] = RecordingSampleBuffer.CHUNK_DURATION_US;
+            mWriteIndexEndPositionUs[i] = RecordingSampleBuffer.MIN_SEEK_DURATION_US;
+            mWriteChunkEndPositionUs[i] = mSampleChunkDurationUs;
             mReadIoStates[i] = new SampleChunk.IoState();
             mWriteIoStates[i] = new SampleChunk.IoState();
         }
@@ -204,6 +220,15 @@
     }
 
     /**
+     * Closes read from the specified track.
+     *
+     * @param index track index
+     */
+    public void closeRead(int index) {
+        mIoHandler.sendMessage(mIoHandler.obtainMessage(MSG_CLOSE_READ, index));
+    }
+
+    /**
      * Notifies writes are finished.
      */
     public void closeWrite() {
@@ -229,21 +254,19 @@
         try {
             if (mBufferReason == RecordingSampleBuffer.BUFFER_REASON_RECORDING && mTrackCount > 0) {
                 // Saves meta information for recording.
-                Pair<String, android.media.MediaFormat> audio = null, video = null;
+                List<BufferManager.TrackFormat> audios = new LinkedList<>();
+                List<BufferManager.TrackFormat> videos = new LinkedList<>();
                 for (int i = 0; i < mTrackCount; ++i) {
                     android.media.MediaFormat format =
                             mMediaFormats.get(i).getFrameworkMediaFormatV16();
                     format.setLong(android.media.MediaFormat.KEY_DURATION, mBufferDurationUs);
-                    if (audio == null && MimeTypes.isAudio(mMediaFormats.get(i).mimeType)) {
-                        audio = new Pair<>(mIds.get(i), format);
-                    } else if (video == null && MimeTypes.isVideo(mMediaFormats.get(i).mimeType)) {
-                        video = new Pair<>(mIds.get(i), format);
-                    }
-                    if (audio != null && video != null) {
-                        break;
+                    if (MimeTypes.isAudio(mMediaFormats.get(i).mimeType)) {
+                        audios.add(new BufferManager.TrackFormat(mIds.get(i), format));
+                    } else if (MimeTypes.isVideo(mMediaFormats.get(i).mimeType)) {
+                        videos.add(new BufferManager.TrackFormat(mIds.get(i), format));
                     }
                 }
-                mBufferManager.writeMetaFiles(audio, video);
+                mBufferManager.writeMetaFiles(audios, videos);
             }
         } finally {
             mBufferManager.release();
@@ -265,6 +288,9 @@
                 case MSG_OPEN_WRITE:
                     doOpenWrite((int) message.obj);
                     return true;
+                case MSG_CLOSE_READ:
+                    doCloseRead((int) message.obj);
+                    return true;
                 case MSG_CLOSE_WRITE:
                     doCloseWrite();
                     return true;
@@ -291,14 +317,16 @@
     private void doOpenRead(IoParams params) throws IOException {
         int index = params.index;
         mIoHandler.removeMessages(MSG_READ, index);
-        SampleChunk chunk = mBufferManager.getReadFile(mIds.get(index), params.positionUs);
-        if (chunk == null) {
+        Pair<SampleChunk, Integer> readPosition =
+                mBufferManager.getReadFile(mIds.get(index), params.positionUs);
+        if (readPosition == null) {
             String errorMessage = "Chunk ID:" + mIds.get(index) + " pos:" + params.positionUs
                     + "is not found";
-            SoftPreconditions.checkNotNull(chunk, TAG, errorMessage);
+            SoftPreconditions.checkNotNull(readPosition, TAG, errorMessage);
             throw new IOException(errorMessage);
         }
-        mReadIoStates[index].openRead(chunk);
+        mSelectedTracks.add(index);
+        mReadIoStates[index].openRead(readPosition.first, (long) readPosition.second);
         if (mHandlerReadSampleBuffers[index] != null) {
             SampleHolder sample;
             while ((sample = mHandlerReadSampleBuffers[index].poll()) != null) {
@@ -310,10 +338,22 @@
     }
 
     private void doOpenWrite(int index) throws IOException {
-        SampleChunk chunk = mBufferManager.createNewWriteFile(mIds.get(index), 0, mSamplePool);
+        SampleChunk chunk = mBufferManager.createNewWriteFileIfNeeded(mIds.get(index), 0,
+                mSamplePool, null, 0);
         mWriteIoStates[index].openWrite(chunk);
     }
 
+    private void doCloseRead(int index) {
+        mSelectedTracks.remove(index);
+        if (mHandlerReadSampleBuffers[index] != null) {
+            SampleHolder sample;
+            while ((sample = mHandlerReadSampleBuffers[index].poll()) != null) {
+                mSamplePool.releaseSample(sample);
+            }
+        }
+        mIoHandler.removeMessages(MSG_READ, index);
+    }
+
     private void doRead(int index) throws IOException {
         mIoHandler.removeMessages(MSG_READ, index);
         if (mHandlerReadSampleBuffers[index].size() >= MAX_READ_BUFFER_SAMPLES) {
@@ -357,13 +397,21 @@
                 if (sample.timeUs > mBufferDurationUs) {
                     mBufferDurationUs = sample.timeUs;
                 }
-
-                if (sample.timeUs >= mWriteEndPositionUs[index]) {
-                    nextChunk = mBufferManager.createNewWriteFile(mIds.get(index),
-                            mWriteEndPositionUs[index], mSamplePool);
-                    mWriteEndPositionUs[index] =
-                            ((sample.timeUs / RecordingSampleBuffer.CHUNK_DURATION_US) + 1) *
-                                    RecordingSampleBuffer.CHUNK_DURATION_US;
+                if (sample.timeUs >= mWriteIndexEndPositionUs[index]) {
+                    SampleChunk currentChunk = sample.timeUs >= mWriteChunkEndPositionUs[index] ?
+                            null : mWriteIoStates[params.index].getChunk();
+                    int currentOffset = (int) mWriteIoStates[params.index].getOffset();
+                    nextChunk = mBufferManager.createNewWriteFileIfNeeded(
+                            mIds.get(index), mWriteIndexEndPositionUs[index], mSamplePool,
+                            currentChunk, currentOffset);
+                    mWriteIndexEndPositionUs[index] =
+                            ((sample.timeUs / RecordingSampleBuffer.MIN_SEEK_DURATION_US) + 1) *
+                                    RecordingSampleBuffer.MIN_SEEK_DURATION_US;
+                    if (nextChunk != null) {
+                        mWriteChunkEndPositionUs[index] =
+                                ((sample.timeUs / mSampleChunkDurationUs) + 1)
+                                        * mSampleChunkDurationUs;
+                    }
                 }
             }
             mWriteIoStates[params.index].write(params.sample, nextChunk);
@@ -391,15 +439,22 @@
         mIoHandler.removeCallbacksAndMessages(null);
         mFinished = true;
         conditionVariable.open();
+        mSelectedTracks.clear();
     }
 
     private void releaseEvictedChunks() {
-        if (mBufferReason != RecordingSampleBuffer.BUFFER_REASON_LIVE_PLAYBACK) {
+        if (mBufferReason != RecordingSampleBuffer.BUFFER_REASON_LIVE_PLAYBACK
+                || mSelectedTracks.isEmpty()) {
             return;
         }
+        long currentStartPositionUs = Long.MAX_VALUE;
+        for (int trackIndex : mSelectedTracks) {
+            currentStartPositionUs = Math.min(currentStartPositionUs,
+                    mReadIoStates[trackIndex].getStartPositionUs());
+        }
         for (int i = 0; i < mTrackCount; ++i) {
             long evictEndPositionUs = Math.min(mBufferManager.getStartPositionUs(mIds.get(i)),
-                    mReadIoStates[i].getStartPositionUs());
+                    currentStartPositionUs);
             mBufferManager.evictChunks(mIds.get(i), evictEndPositionUs);
         }
     }
diff --git a/src/com/android/tv/tuner/exoplayer/buffer/SampleQueue.java b/src/com/android/tv/tuner/exoplayer/buffer/SampleQueue.java
index 7b098f4..75eac5a 100644
--- a/src/com/android/tv/tuner/exoplayer/buffer/SampleQueue.java
+++ b/src/com/android/tv/tuner/exoplayer/buffer/SampleQueue.java
@@ -43,6 +43,7 @@
         if (sampleFromQueue == null) {
             return SampleSource.NOTHING_READ;
         }
+        sample.ensureSpaceForWrite(sampleFromQueue.size);
         sample.size = sampleFromQueue.size;
         sample.flags = sampleFromQueue.flags;
         sample.timeUs = sampleFromQueue.timeUs;
diff --git a/src/com/android/tv/tuner/exoplayer/buffer/SimpleSampleBuffer.java b/src/com/android/tv/tuner/exoplayer/buffer/SimpleSampleBuffer.java
index 40c4ef9..159fde1 100644
--- a/src/com/android/tv/tuner/exoplayer/buffer/SimpleSampleBuffer.java
+++ b/src/com/android/tv/tuner/exoplayer/buffer/SimpleSampleBuffer.java
@@ -19,18 +19,18 @@
 import android.os.ConditionVariable;
 
 import android.support.annotation.NonNull;
+
 import com.google.android.exoplayer.C;
 import com.google.android.exoplayer.MediaFormat;
 import com.google.android.exoplayer.SampleHolder;
 import com.google.android.exoplayer.SampleSource;
+import com.android.tv.common.SoftPreconditions;
 import com.android.tv.tuner.tvinput.PlaybackBufferListener;
 import com.android.tv.tuner.exoplayer.SampleExtractor;
 
 import java.io.IOException;
 import java.util.List;
 
-import junit.framework.Assert;
-
 /**
  * Handles I/O for {@link SampleExtractor} when
  * physical storage based buffer is not used. Trickplay is disabled.
@@ -115,8 +115,8 @@
     @Override
     public synchronized int readSample(int track, SampleHolder sampleHolder) {
         SampleQueue queue = mPlayingSampleQueues[track];
-        Assert.assertNotNull(queue);
-        int result = queue.dequeueSample(sampleHolder);
+        SoftPreconditions.checkNotNull(queue);
+        int result = queue == null ? SampleSource.NOTHING_READ : queue.dequeueSample(sampleHolder);
         if (result != SampleSource.SAMPLE_READ && reachedEos()) {
             return SampleSource.END_OF_STREAM;
         }
diff --git a/src/com/android/tv/tuner/exoplayer/buffer/TrickplayStorageManager.java b/src/com/android/tv/tuner/exoplayer/buffer/TrickplayStorageManager.java
index 258a5cd..9fe921b 100644
--- a/src/com/android/tv/tuner/exoplayer/buffer/TrickplayStorageManager.java
+++ b/src/com/android/tv/tuner/exoplayer/buffer/TrickplayStorageManager.java
@@ -17,20 +17,23 @@
 package com.android.tv.tuner.exoplayer.buffer;
 
 import android.content.Context;
-import android.media.MediaFormat;
 import android.os.AsyncTask;
-import android.os.Looper;
 import android.provider.Settings;
+import android.support.annotation.NonNull;
 import android.util.Pair;
 
+import com.android.tv.common.SoftPreconditions;
+
 import java.io.File;
 import java.util.ArrayList;
+import java.util.List;
 import java.util.SortedMap;
 
 /**
  * Manages Trickplay storage.
  */
 public class TrickplayStorageManager implements BufferManager.StorageManager {
+    // TODO: Support multi-sessions.
     private static final String BUFFER_DIR = "timeshift";
 
     // Copied from android.provider.Settings.Global (hidden fields)
@@ -43,53 +46,68 @@
     private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10;
     private static final long DEFAULT_THRESHOLD_MAX_BYTES = 500L * 1024 * 1024;
 
-    private final File mBufferDir;
+    private static AsyncTask<Void, Void, Void> sLastCacheCleanUpTask;
+    private static File sBufferDir;
+    private static long sStorageBufferBytes;
+
     private final long mMaxBufferSize;
-    private final long mStorageBufferBytes;
 
-    private static long getStorageBufferBytes(Context context, File path) {
-        long lowPercentage = Settings.Global.getInt(context.getContentResolver(),
-                SYS_STORAGE_THRESHOLD_PERCENTAGE, DEFAULT_THRESHOLD_PERCENTAGE);
-        long lowBytes = path.getTotalSpace() * lowPercentage / 100;
-        long maxLowBytes = Settings.Global.getLong(context.getContentResolver(),
-                SYS_STORAGE_THRESHOLD_MAX_BYTES, DEFAULT_THRESHOLD_MAX_BYTES);
-        return Math.min(lowBytes, maxLowBytes);
-    }
-
-    public TrickplayStorageManager(Context context, File baseDir, long maxBufferSize) {
-        mBufferDir = new File(baseDir, BUFFER_DIR);
-        mBufferDir.mkdirs();
-        mMaxBufferSize = maxBufferSize;
-        clearStorage();
-        mStorageBufferBytes = getStorageBufferBytes(context, mBufferDir);
-    }
-
-    @Override
-    public void clearStorage() {
-        File files[] = mBufferDir.listFiles();
-        if (files == null || files.length == 0) {
+    private static void initParamsIfNeeded(Context context, @NonNull File path) {
+        // TODO: Support multi-sessions.
+        SoftPreconditions.checkState(
+                sBufferDir == null || sBufferDir.equals(path));
+        if (path.equals(sBufferDir)) {
             return;
         }
-        if (Looper.myLooper() == Looper.getMainLooper()) {
-            new AsyncTask<Void, Void, Void>() {
-                @Override
-                protected Void doInBackground(Void... params) {
-                    for (File file : files) {
-                        file.delete();
-                    }
+        sBufferDir = path;
+        long lowPercentage = Settings.Global.getInt(context.getContentResolver(),
+                SYS_STORAGE_THRESHOLD_PERCENTAGE, DEFAULT_THRESHOLD_PERCENTAGE);
+        long lowPercentageToBytes = path.getTotalSpace() * lowPercentage / 100;
+        long maxLowBytes = Settings.Global.getLong(context.getContentResolver(),
+                SYS_STORAGE_THRESHOLD_MAX_BYTES, DEFAULT_THRESHOLD_MAX_BYTES);
+        sStorageBufferBytes = Math.min(lowPercentageToBytes, maxLowBytes);
+    }
+
+    public TrickplayStorageManager(Context context, @NonNull File baseDir, long maxBufferSize) {
+        initParamsIfNeeded(context, new File(baseDir, BUFFER_DIR));
+        sBufferDir.mkdirs();
+        mMaxBufferSize = maxBufferSize;
+        clearStorage();
+    }
+
+    private void clearStorage() {
+        long now = System.currentTimeMillis();
+        if (sLastCacheCleanUpTask != null) {
+            sLastCacheCleanUpTask.cancel(true);
+        }
+        sLastCacheCleanUpTask = new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                if (isCancelled()) {
                     return null;
                 }
-            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
-        } else {
-            for (File file : files) {
-                file.delete();
+                File files[] = sBufferDir.listFiles();
+                if (files == null || files.length == 0) {
+                    return null;
+                }
+                for (File file : files) {
+                    if (isCancelled()) {
+                        break;
+                    }
+                    long lastModified = file.lastModified();
+                    if (lastModified != 0 && lastModified < now) {
+                        file.delete();
+                    }
+                }
+                return null;
             }
-        }
+        };
+        sLastCacheCleanUpTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
     @Override
     public File getBufferDir() {
-        return mBufferDir;
+        return sBufferDir;
     }
 
     @Override
@@ -104,25 +122,26 @@
 
     @Override
     public boolean hasEnoughBuffer(long pendingDelete) {
-        return mBufferDir.getUsableSpace() + pendingDelete >= mStorageBufferBytes;
+        return sBufferDir.getUsableSpace() + pendingDelete >= sStorageBufferBytes;
     }
 
     @Override
-    public Pair<String, MediaFormat> readTrackInfoFile(boolean isAudio) {
+    public List<BufferManager.TrackFormat> readTrackInfoFiles(boolean isAudio) {
         return null;
     }
 
     @Override
-    public ArrayList<Long> readIndexFile(String trackId) {
+    public ArrayList<BufferManager.PositionHolder> readIndexFile(String trackId) {
         return null;
     }
 
     @Override
-    public void writeTrackInfoFile(String trackId, MediaFormat format, boolean isAudio) {
+    public void writeTrackInfoFiles(List<BufferManager.TrackFormat> formatList, boolean isAudio) {
     }
 
     @Override
-    public void writeIndexFile(String trackName, SortedMap<Long, SampleChunk> index) {
+    public void writeIndexFile(String trackName,
+            SortedMap<Long, Pair<SampleChunk, Integer>> index) {
     }
 
 }
diff --git a/src/com/android/tv/tuner/exoplayer/ffmpeg/FfmpegDecoderClient.java b/src/com/android/tv/tuner/exoplayer/ffmpeg/FfmpegDecoderClient.java
new file mode 100644
index 0000000..356636c
--- /dev/null
+++ b/src/com/android/tv/tuner/exoplayer/ffmpeg/FfmpegDecoderClient.java
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2017 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.tuner.exoplayer.ffmpeg;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import android.support.annotation.MainThread;
+import android.support.annotation.WorkerThread;
+import android.support.annotation.VisibleForTesting;
+import com.google.android.exoplayer.SampleHolder;
+import com.android.tv.Features;
+import com.android.tv.tuner.exoplayer.audio.AudioDecoder;
+
+import java.nio.ByteBuffer;
+
+/**
+ * The class connects {@link FfmpegDecoderService} to decode audio samples.
+ * In order to sandbox ffmpeg based decoder, {@link FfmpegDecoderService} is an isolated process
+ * without any permission and connected by binder.
+ */
+public class FfmpegDecoderClient extends AudioDecoder {
+    private static FfmpegDecoderClient sInstance;
+
+    private IFfmpegDecoder mService;
+    private Boolean mIsAvailable;
+
+    private static final String FFMPEG_DECODER_SERVICE_FILTER =
+            "com.android.tv.tuner.exoplayer.ffmpeg.IFfmpegDecoder";
+    private static final long FFMPEG_SERVICE_CONNECT_TIMEOUT_MS = 500;
+
+    private final ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            mService = IFfmpegDecoder.Stub.asInterface(service);
+            synchronized (FfmpegDecoderClient.this) {
+                try {
+                    mIsAvailable = mService.isAvailable();
+                } catch (RemoteException e) {
+                }
+                FfmpegDecoderClient.this.notify();
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName className) {
+            synchronized (FfmpegDecoderClient.this) {
+                sInstance.releaseLocked();
+                mIsAvailable = false;
+                mService = null;
+            }
+        }
+    };
+
+    /**
+     * Connects to the decoder service for future uses.
+     * @param context
+     * @return {@code true} when decoder service is connected.
+     */
+    @MainThread
+    public synchronized static boolean connect(Context context) {
+        if (Features.AC3_SOFTWARE_DECODE.isEnabled(context)) {
+            if (sInstance == null) {
+                sInstance = new FfmpegDecoderClient();
+                Intent intent =
+                        new Intent(FFMPEG_DECODER_SERVICE_FILTER)
+                                .setComponent(
+                                        new ComponentName(context, FfmpegDecoderService.class));
+                if (context.bindService(intent, sInstance.mConnection, Context.BIND_AUTO_CREATE)) {
+                    return true;
+                } else {
+                    sInstance = null;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Disconnects from the decoder service and release resources.
+     * @param context
+     */
+    @MainThread
+    public synchronized static void disconnect(Context context) {
+        if (sInstance != null) {
+            synchronized (sInstance) {
+                sInstance.releaseLocked();
+                if (sInstance.mIsAvailable != null && sInstance.mIsAvailable) {
+                    context.unbindService(sInstance.mConnection);
+                }
+                sInstance.mIsAvailable = false;
+                sInstance.mService = null;
+            }
+            sInstance = null;
+        }
+    }
+
+    /**
+     * Returns whether service is available or not.
+     * Before using client, this should be used to check availability.
+     */
+    @WorkerThread
+    public synchronized static boolean isAvailable() {
+        if (sInstance != null) {
+            return sInstance.available();
+        }
+        return false;
+    }
+
+    /**
+     * Returns an client instance.
+     */
+    public synchronized static FfmpegDecoderClient getInstance() {
+        if (sInstance != null) {
+            sInstance.createDecoder();
+        }
+        return sInstance;
+    }
+
+    private FfmpegDecoderClient() {
+    }
+
+    private synchronized boolean available() {
+        if (mIsAvailable == null) {
+            try {
+                this.wait(FFMPEG_SERVICE_CONNECT_TIMEOUT_MS);
+            } catch (InterruptedException e) {
+            }
+        }
+        return mIsAvailable != null && mIsAvailable == true;
+    }
+
+    private synchronized void createDecoder() {
+        if (mIsAvailable == null || mIsAvailable == false) {
+            return;
+        }
+        try {
+            mService.create();
+        } catch (RemoteException e) {
+        }
+    }
+
+    private void releaseLocked() {
+        if (mIsAvailable == null || mIsAvailable == false) {
+            return;
+        }
+        try {
+          mService.release();
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public synchronized void release() {
+        releaseLocked();
+    }
+
+    @Override
+    public synchronized void decode(SampleHolder sampleHolder) {
+        if (mIsAvailable == null || mIsAvailable == false) {
+            return;
+        }
+        byte[] sampleBytes = new byte [sampleHolder.data.limit()];
+        sampleHolder.data.get(sampleBytes, 0, sampleBytes.length);
+        try {
+            mService.decode(sampleHolder.timeUs, sampleBytes);
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public synchronized void resetDecoderState(String mimeType) {
+        if (mIsAvailable == null || mIsAvailable == false) {
+            return;
+        }
+        try {
+            mService.resetDecoderState(mimeType);
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public synchronized ByteBuffer getDecodedSample() {
+        if (mIsAvailable == null || mIsAvailable == false) {
+            return null;
+        }
+        try {
+            byte[] outputBytes = mService.getDecodedSample();
+            if (outputBytes != null && outputBytes.length > 0) {
+                return ByteBuffer.wrap(outputBytes);
+            }
+        } catch (RemoteException e) {
+        }
+        return null;
+    }
+
+    @Override
+    public synchronized long getDecodedTimeUs() {
+        if (mIsAvailable == null || mIsAvailable == false) {
+            return 0;
+        }
+        try {
+            return mService.getDecodedTimeUs();
+        } catch (RemoteException e) {
+        }
+        return 0;
+    }
+
+    @VisibleForTesting
+    public boolean testSandboxIsolatedProcess() {
+        // When testing isolated process, we will check the permission in FfmpegDecoderService.
+        // If the service have any permission, an exception will be thrown.
+        try {
+            mService.testSandboxIsolatedProcess();
+        } catch (RemoteException e) {
+            return false;
+        }
+        return true;
+    }
+
+    @VisibleForTesting
+    public void testSandboxMinijail() {
+        // When testing minijail, we will call a system call which is blocked by minijail. In that
+        // case, the FfmpegDecoderService will be disconnected, we can check the connection status
+        // to make sure if the minijail works or not.
+        try {
+            mService.testSandboxMinijail();
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/src/com/android/tv/tuner/exoplayer/ffmpeg/FfmpegDecoderService.java b/src/com/android/tv/tuner/exoplayer/ffmpeg/FfmpegDecoderService.java
new file mode 100644
index 0000000..3ebdd38
--- /dev/null
+++ b/src/com/android/tv/tuner/exoplayer/ffmpeg/FfmpegDecoderService.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2017 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.tuner.exoplayer.ffmpeg;
+
+import android.app.Service;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.os.AsyncTask;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import com.google.android.exoplayer2.ext.ffmpeg.FfmpegAudioDecoder;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+/**
+ * Ffmpeg based audio decoder service.
+ * It should be isolatedProcess due to security reason.
+ */
+public class FfmpegDecoderService extends Service {
+    private static final String TAG = "FfmpegDecoderService";
+    private static final boolean DEBUG = false;
+
+    private static final String POLICY_FILE = "whitelist.policy";
+
+    private static final long MINIJAIL_SETUP_WAIT_TIMEOUT_MS = 5000;
+
+    private static boolean sLibraryLoaded = true;
+
+    static {
+        try {
+            System.loadLibrary("minijail_jni");
+        } catch (Exception | Error e) {
+            Log.e(TAG, "Load minijail failed:", e);
+            sLibraryLoaded = false;
+        }
+    }
+
+    private FfmpegDecoder mBinder = new FfmpegDecoder();
+    private volatile Object mMinijailSetupMonitor = new Object();
+    //@GuardedBy("mMinijailSetupMonitor")
+    private volatile Boolean mMinijailSetup;
+
+    @Override
+    public void onCreate() {
+        if (sLibraryLoaded) {
+            new AsyncTask<Void, Void, Void>() {
+                @Override
+                protected Void doInBackground(Void... params) {
+                    synchronized (mMinijailSetupMonitor) {
+                        int pipeFd = getPolicyPipeFd();
+                        if (pipeFd <= 0) {
+                            Log.e(TAG, "fail to open policy file");
+                            mMinijailSetup = false;
+                        } else {
+                            nativeSetupMinijail(pipeFd);
+                            mMinijailSetup = true;
+                            if (DEBUG) Log.d(TAG, "Minijail setup successfully");
+                        }
+                        mMinijailSetupMonitor.notify();
+                    }
+                    return null;
+                }
+            }.execute();
+        } else {
+            synchronized (mMinijailSetupMonitor) {
+                mMinijailSetup = false;
+                mMinijailSetupMonitor.notify();
+            }
+        }
+        super.onCreate();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    private int getPolicyPipeFd() {
+        try {
+            ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
+            final ParcelFileDescriptor.AutoCloseOutputStream outputStream =
+                    new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);
+            final AssetFileDescriptor policyFile = getAssets().openFd("whitelist.policy");
+            final byte[] buffer = new byte[2048];
+            final FileInputStream policyStream = policyFile.createInputStream();
+            while (true) {
+                int bytesRead = policyStream.read(buffer);
+                if (bytesRead == -1) break;
+                outputStream.write(buffer, 0, bytesRead);
+            }
+            policyStream.close();
+            outputStream.close();
+            return pipe[0].detachFd();
+        } catch (IOException e) {
+            Log.e(TAG, "Policy file not found:" + e);
+        }
+        return -1;
+    }
+
+    private final class FfmpegDecoder extends IFfmpegDecoder.Stub {
+        FfmpegAudioDecoder mDecoder;
+        @Override
+        public boolean isAvailable() {
+            return isMinijailSetupDone() && FfmpegAudioDecoder.isAvailable();
+        }
+
+        @Override
+        public void create() {
+            mDecoder = new FfmpegAudioDecoder(FfmpegDecoderService.this);
+        }
+
+        @Override
+        public void release() {
+            if (mDecoder != null) {
+                mDecoder.release();
+                mDecoder = null;
+            }
+        }
+
+        @Override
+        public void decode(long timeUs, byte[] sample) {
+            if (!isMinijailSetupDone()) {
+                // If minijail is not setup, we don't run decode for better security.
+                return;
+            }
+            mDecoder.decode(timeUs, sample);
+        }
+
+        @Override
+        public void resetDecoderState(String mimetype) {
+            mDecoder.resetDecoderState(mimetype);
+        }
+
+        @Override
+        public byte[] getDecodedSample() {
+            ByteBuffer decodedBuffer = mDecoder.getDecodedSample();
+            byte[] ret = new byte[decodedBuffer.limit()];
+            decodedBuffer.get(ret, 0, ret.length);
+            return ret;
+        }
+
+        @Override
+        public long getDecodedTimeUs() {
+            return mDecoder.getDecodedTimeUs();
+        }
+
+        private boolean isMinijailSetupDone() {
+            synchronized (mMinijailSetupMonitor) {
+                if (DEBUG) Log.d(TAG, "mMinijailSetup in isAvailable(): " + mMinijailSetup);
+                if (mMinijailSetup == null) {
+                    try {
+                        if (DEBUG) Log.d(TAG, "Wait till Minijail setup is done");
+                        mMinijailSetupMonitor.wait(MINIJAIL_SETUP_WAIT_TIMEOUT_MS);
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                    }
+                }
+                return mMinijailSetup != null && mMinijailSetup;
+            }
+        }
+
+        @Override
+        public void testSandboxIsolatedProcess() {
+            if (!isMinijailSetupDone()) {
+                // If minijail is not setup, we return directly to make the test fail.
+                return;
+            }
+            if (FfmpegDecoderService.this.checkSelfPermission("android.permission.INTERNET")
+                    == PackageManager.PERMISSION_GRANTED) {
+                throw new SecurityException("Shouldn't have the permission of internet");
+            }
+        }
+
+        @Override
+        public void testSandboxMinijail() {
+            if (!isMinijailSetupDone()) {
+                // If minijail is not setup, we return directly to make the test fail.
+                return;
+            }
+            nativeTestMinijail();
+        }
+    }
+
+    private native void nativeSetupMinijail(int policyFd);
+    private native void nativeTestMinijail();
+}
diff --git a/src/com/android/tv/tuner/exoplayer/ffmpeg/IFfmpegDecoder.aidl b/src/com/android/tv/tuner/exoplayer/ffmpeg/IFfmpegDecoder.aidl
new file mode 100644
index 0000000..ed05379
--- /dev/null
+++ b/src/com/android/tv/tuner/exoplayer/ffmpeg/IFfmpegDecoder.aidl
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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.tuner.exoplayer.ffmpeg;
+
+interface IFfmpegDecoder {
+    boolean isAvailable();
+    void create();
+    void release();
+    void resetDecoderState(String mimetype);
+    void decode(long timeUs, in byte[] sample);
+    byte[] getDecodedSample();
+    long getDecodedTimeUs();
+    void testSandboxIsolatedProcess();
+    void testSandboxMinijail();
+}
\ No newline at end of file
diff --git a/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java b/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java
index 97d9ece..e0e21a2 100644
--- a/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java
+++ b/src/com/android/tv/tuner/setup/ConnectionTypeFragment.java
@@ -21,6 +21,7 @@
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
 import android.support.v17.leanback.widget.GuidedAction;
 
+import com.android.tv.common.BuildConfig;
 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.tuner.R;
@@ -36,6 +37,24 @@
             "com.android.tv.tuner.setup.ConnectionTypeFragment";
 
     @Override
+    public void onCreate(Bundle savedInstanceState) {
+        ((TunerSetupActivity) getActivity()).generateTunerHal();
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    public void onResume() {
+        ((TunerSetupActivity) getActivity()).generateTunerHal();
+        super.onResume();
+    }
+
+    @Override
+    public void onDestroy() {
+        ((TunerSetupActivity) getActivity()).clearTunerHal();
+        super.onDestroy();
+    }
+
+    @Override
     protected SetupGuidedStepFragment onCreateContentFragment() {
         return new ContentFragment();
     }
diff --git a/src/com/android/tv/tuner/setup/PostalCodeFragment.java b/src/com/android/tv/tuner/setup/PostalCodeFragment.java
new file mode 100644
index 0000000..025b919
--- /dev/null
+++ b/src/com/android/tv/tuner/setup/PostalCodeFragment.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2017 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.tuner.setup;
+
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
+import android.support.v17.leanback.widget.GuidedAction;
+import android.support.v17.leanback.widget.GuidedActionsStylist;
+import android.text.InputFilter;
+import android.text.InputFilter.AllCaps;
+import android.view.View;
+import android.widget.TextView;
+import com.android.tv.R;
+import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
+import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
+import com.android.tv.tuner.util.PostalCodeUtils;
+import com.android.tv.util.LocationUtils;
+import java.util.List;
+
+/**
+ * A fragment for initial screen.
+ */
+public class PostalCodeFragment extends SetupMultiPaneFragment {
+    public static final String ACTION_CATEGORY =
+            "com.android.tv.tuner.setup.PostalCodeFragment";
+    private static final int VIEW_TYPE_EDITABLE = 1;
+
+    @Override
+    protected SetupGuidedStepFragment onCreateContentFragment() {
+        ContentFragment fragment = new ContentFragment();
+        Bundle arguments = new Bundle();
+        arguments.putBoolean(SetupGuidedStepFragment.KEY_THREE_PANE, true);
+        fragment.setArguments(arguments);
+        return fragment;
+    }
+
+    @Override
+    protected String getActionCategory() {
+        return ACTION_CATEGORY;
+    }
+
+    @Override
+    protected boolean needsDoneButton() {
+        return true;
+    }
+
+    @Override
+    protected boolean needsSkipButton() {
+        return true;
+    }
+
+    @Override
+    protected void setOnClickAction(View view, final String category, final int actionId) {
+        if (actionId == ACTION_DONE) {
+            view.setOnClickListener(
+                    new View.OnClickListener() {
+                        @Override
+                        public void onClick(View view) {
+                            CharSequence postalCode =
+                                    ((ContentFragment) getContentFragment()).mEditAction.getTitle();
+                            String region = LocationUtils.getCurrentCountry(getContext());
+                            if (postalCode != null && PostalCodeUtils.matches(postalCode, region)) {
+                                PostalCodeUtils.setLastPostalCode(
+                                        getContext(), postalCode.toString());
+                                onActionClick(category, actionId);
+                            } else {
+                                ContentFragment contentFragment =
+                                        (ContentFragment) getContentFragment();
+                                contentFragment.mEditAction.setDescription(
+                                        getString(R.string.postal_code_invalid_warning));
+                                contentFragment.notifyActionChanged(0);
+                                contentFragment.mEditedActionView.performClick();
+                            }
+                        }
+                    });
+        } else if (actionId == ACTION_SKIP) {
+            super.setOnClickAction(view, category, ACTION_SKIP);
+        }
+    }
+
+    public static class ContentFragment extends SetupGuidedStepFragment {
+        private GuidedAction mEditAction;
+        private View mEditedActionView;
+        private View mDoneActionView;
+        private boolean mProceed;
+
+        @Override
+        public void onGuidedActionFocused(GuidedAction action) {
+            if (action.equals(mEditAction)) {
+                if (mProceed) {
+                    // "NEXT" in IME was just clicked, moves focus to Done button.
+                    if (mDoneActionView == null) {
+                        mDoneActionView = getActivity().findViewById(R.id.button_done);
+                    }
+                    mDoneActionView.requestFocus();
+                    mProceed = false;
+                } else {
+                    // Directly opens IME to input postal/zip code.
+                    if (mEditedActionView == null) {
+                        int maxLength = PostalCodeUtils.getRegionMaxLength(getContext());
+                        mEditedActionView = getView().findViewById(R.id.guidedactions_editable);
+                        ((TextView) mEditedActionView.findViewById(R.id.guidedactions_item_title))
+                                .setFilters(
+                                        new InputFilter[] {
+                                            new InputFilter.LengthFilter(maxLength), new AllCaps()
+                                        });
+                    }
+                    mEditedActionView.performClick();
+                }
+            }
+        }
+
+        @Override
+        public long onGuidedActionEditedAndProceed(GuidedAction action) {
+            mProceed = true;
+            return 0;
+        }
+
+        @NonNull
+        @Override
+        public Guidance onCreateGuidance(Bundle savedInstanceState) {
+            String title = getString(R.string.postal_code_guidance_title);
+            String description = getString(R.string.postal_code_guidance_description);
+            String breadcrumb = getString(R.string.ut_setup_breadcrumb);
+            return new Guidance(title, description, breadcrumb, null);
+        }
+
+        @Override
+        public void onCreateActions(@NonNull List<GuidedAction> actions,
+                Bundle savedInstanceState) {
+            String description = getString(R.string.postal_code_action_description);
+            mEditAction = new GuidedAction.Builder(getActivity()).id(0).editable(true)
+                    .description(description).build();
+            actions.add(mEditAction);
+        }
+
+        @Override
+        protected String getActionCategory() {
+            return ACTION_CATEGORY;
+        }
+
+        @Override
+        public GuidedActionsStylist onCreateActionsStylist() {
+            return new GuidedActionsStylist() {
+                @Override
+                public int getItemViewType(GuidedAction action) {
+                    if (action.isEditable()) {
+                        return VIEW_TYPE_EDITABLE;
+                    }
+                    return super.getItemViewType(action);
+                }
+
+                @Override
+                public int onProvideItemLayoutId(int viewType) {
+                    if (viewType == VIEW_TYPE_EDITABLE) {
+                        return R.layout.guided_action_editable;
+                    }
+                    return super.onProvideItemLayoutId(viewType);
+                }
+            };
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/tuner/setup/ScanFragment.java b/src/com/android/tv/tuner/setup/ScanFragment.java
index 3b61deb..b6936e3 100644
--- a/src/com/android/tv/tuner/setup/ScanFragment.java
+++ b/src/com/android/tv/tuner/setup/ScanFragment.java
@@ -21,6 +21,7 @@
 import android.app.ProgressDialog;
 import android.content.Context;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.ConditionVariable;
 import android.os.Handler;
@@ -35,25 +36,21 @@
 import android.widget.ProgressBar;
 import android.widget.TextView;
 
-import com.android.tv.common.AutoCloseableUtils;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.ui.setup.SetupFragment;
 import com.android.tv.tuner.ChannelScanFileParser;
-import com.android.tv.tuner.TunerHal;
 import com.android.tv.tuner.R;
+import com.android.tv.tuner.TunerHal;
 import com.android.tv.tuner.TunerPreferences;
-import com.android.tv.tuner.data.nano.Channel;
 import com.android.tv.tuner.data.PsipData;
 import com.android.tv.tuner.data.TunerChannel;
+import com.android.tv.tuner.data.nano.Channel;
 import com.android.tv.tuner.source.FileTsStreamer;
 import com.android.tv.tuner.source.TsDataSource;
 import com.android.tv.tuner.source.TsStreamer;
 import com.android.tv.tuner.source.TunerTsStreamer;
 import com.android.tv.tuner.tvinput.ChannelDataManager;
 import com.android.tv.tuner.tvinput.EventDetector;
-import com.android.tv.tuner.util.TunerInputInfoUtils;
-
-import junit.framework.Assert;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -67,6 +64,7 @@
 public class ScanFragment extends SetupFragment {
     private static final String TAG = "ScanFragment";
     private static final boolean DEBUG = false;
+
     // In the fake mode, the connection to antenna or cable is not necessary.
     // Instead dummy channels are added.
     private static final boolean FAKE_MODE = false;
@@ -98,6 +96,7 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
+        if (DEBUG) Log.d(TAG, "onCreateView");
         View view = super.onCreateView(inflater, container, savedInstanceState);
         mChannelDataManager = new ChannelDataManager(getActivity());
         mChannelDataManager.checkDataVersion(getActivity());
@@ -120,13 +119,19 @@
             }
         });
         Bundle args = getArguments();
+        int tunerType = (args == null ? 0 : args.getInt(TunerSetupActivity.KEY_TUNER_TYPE, 0));
         // TODO: Handle the case when the fragment is restored.
         startScan(args == null ? 0 : args.getInt(EXTRA_FOR_CHANNEL_SCAN_FILE, 0));
         TextView scanTitleView = (TextView) view.findViewById(R.id.tune_title);
-        if (TunerInputInfoUtils.isBuiltInTuner(getActivity())){
-            scanTitleView.setText(R.string.bt_channel_scan);
-        } else {
-            scanTitleView.setText(R.string.ut_channel_scan);
+        switch (tunerType) {
+            case TunerHal.TUNER_TYPE_USB:
+                scanTitleView.setText(R.string.ut_channel_scan);
+                break;
+            case TunerHal.TUNER_TYPE_NETWORK:
+                scanTitleView.setText(R.string.nt_channel_scan);
+                break;
+            default:
+                scanTitleView.setText(R.string.bt_channel_scan);
         }
         return view;
     }
@@ -147,12 +152,14 @@
     }
 
     @Override
-    public void onDetach() {
+    public void onPause() {
+        Log.d(TAG, "onPause");
         if (mChannelScanTask != null) {
             // Ensure scan task will stop.
+            Log.w(TAG, "The activity went to the background. Stopping channel scan.");
             mChannelScanTask.stopScan();
         }
-        super.onDetach();
+        super.onPause();
     }
 
     /**
@@ -168,7 +175,9 @@
             new Handler().postDelayed(new Runnable() {
                 @Override
                 public void run() {
-                    mChannelScanTask.showFinishingProgressDialog();
+                    if (mChannelScanTask != null) {
+                        mChannelScanTask.showFinishingProgressDialog();
+                    }
                 }
             }, SHOW_PROGRESS_DIALOG_DELAY_MS);
 
@@ -255,13 +264,13 @@
             if (FAKE_MODE) {
                 mScanTsStreamer = new FakeTsStreamer(this);
             } else {
-                TunerHal hal = TunerHal.createInstance(mActivity.getApplicationContext());
+                TunerHal hal = ((TunerSetupActivity) mActivity).getTunerHal();
                 if (hal == null) {
                     throw new RuntimeException("Failed to open a DVB device");
                 }
                 mScanTsStreamer = new TunerTsStreamer(hal, this);
             }
-            mFileTsStreamer = SCAN_LOCAL_STREAMS ? new FileTsStreamer(this) : null;
+            mFileTsStreamer = SCAN_LOCAL_STREAMS ? new FileTsStreamer(this, mActivity) : null;
             mConditionStopped = new ConditionVariable();
             mChannelDataManager.setChannelScanListener(this, new Handler());
         }
@@ -316,10 +325,17 @@
 
         @Override
         protected void onProgressUpdate(Integer... values) {
-            mProgressBar.setProgress(values[0]);
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                mProgressBar.setProgress(values[0], true);
+            } else {
+                mProgressBar.setProgress(values[0]);
+            }
         }
 
         private void stopScan() {
+            if (mLatch != null) {
+                mLatch.countDown();
+            }
             mConditionStopped.open();
         }
 
@@ -340,8 +356,8 @@
                 Log.i(TAG, "Tuning to " + frequency + " " + modulation);
 
                 TsStreamer streamer = getStreamer(scanChannel.type);
-                Assert.assertNotNull(streamer);
-                if (streamer.startStream(scanChannel)) {
+                SoftPreconditions.checkNotNull(streamer);
+                if (streamer != null && streamer.startStream(scanChannel)) {
                     mLatch = new CountDownLatch(1);
                     try {
                         mLatch.await(CHANNEL_SCAN_PERIOD_MS, TimeUnit.MILLISECONDS);
@@ -360,11 +376,7 @@
                 if (mConditionStopped.block(-1)) {
                     break;
                 }
-                onProgressUpdate(MAX_PROGRESS * i++ / mScanChannelList.size());
-            }
-            if (mScanTsStreamer instanceof TunerTsStreamer) {
-                AutoCloseableUtils.closeQuietly(
-                        ((TunerTsStreamer) mScanTsStreamer).getTunerHal());
+                publishProgress(MAX_PROGRESS * i++ / mScanChannelList.size());
             }
             mChannelDataManager.notifyScanCompleted();
             if (!mConditionStopped.block(-1)) {
@@ -427,8 +439,8 @@
                 // Playbacks with video-only stream have not been tested yet.
                 // No video-only channel has been found.
                 addChannel(channel);
+                mChannelDataManager.notifyChannelDetected(channel, channelArrivedAtFirstTime);
             }
-            mChannelDataManager.notifyChannelDetected(channel, channelArrivedAtFirstTime);
         }
 
         public void showFinishingProgressDialog() {
@@ -446,15 +458,21 @@
             mIsFinished = true;
             TunerPreferences.setScannedChannelCount(mActivity.getApplicationContext(),
                     mChannelDataManager.getScannedChannelCount());
-            // Cancel a previously shown recommendation card.
-            TunerSetupActivity.cancelRecommendationCard(mActivity.getApplicationContext());
+            // Cancel a previously shown notification.
+            TunerSetupActivity.cancelNotification(mActivity.getApplicationContext());
             // Mark scan as done
             TunerPreferences.setScanDone(mActivity.getApplicationContext());
             // finishing will be done manually.
             if (mFinishingProgressDialog != null) {
                 mFinishingProgressDialog.dismiss();
             }
-            onActionClick(ACTION_CATEGORY, mIsCanceled ? ACTION_CANCEL : ACTION_FINISH);
+            // If the fragment is not resumed, the next fragment (scan result page) can't be
+            // displayed. In that case, just close the activity.
+            if (isResumed()) {
+                onActionClick(ACTION_CATEGORY, mIsCanceled ? ACTION_CANCEL : ACTION_FINISH);
+            } else if (getActivity() != null) {
+                getActivity().finish();
+            }
             mChannelScanTask = null;
         }
     }
diff --git a/src/com/android/tv/tuner/setup/ScanResultFragment.java b/src/com/android/tv/tuner/setup/ScanResultFragment.java
index 068543c..3b8cd82 100644
--- a/src/com/android/tv/tuner/setup/ScanResultFragment.java
+++ b/src/com/android/tv/tuner/setup/ScanResultFragment.java
@@ -26,6 +26,7 @@
 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.tuner.R;
+import com.android.tv.tuner.TunerHal;
 import com.android.tv.tuner.TunerPreferences;
 import com.android.tv.tuner.util.TunerInputInfoUtils;
 
@@ -76,11 +77,19 @@
                         mChannelCountOnPreference, mChannelCountOnPreference);
                 breadcrumb = null;
             } else {
+                Bundle args = getArguments();
+                int tunerType =
+                        (args == null ? 0 : args.getInt(TunerSetupActivity.KEY_TUNER_TYPE, 0));
                 title = getString(R.string.ut_result_not_found_title);
-                if (TunerInputInfoUtils.isBuiltInTuner(getActivity())) {
-                    description = getString(R.string.bt_result_not_found_description);
-                } else {
-                    description = getString(R.string.ut_result_not_found_description);
+                switch (tunerType) {
+                    case TunerHal.TUNER_TYPE_USB:
+                        description = getString(R.string.ut_result_not_found_description);
+                        break;
+                    case TunerHal.TUNER_TYPE_NETWORK:
+                        description = getString(R.string.nt_result_not_found_description);
+                        break;
+                    default:
+                        description = getString(R.string.bt_result_not_found_description);
                 }
                 breadcrumb = getString(R.string.ut_setup_breadcrumb);
             }
diff --git a/src/com/android/tv/tuner/setup/TunerSetupActivity.java b/src/com/android/tv/tuner/setup/TunerSetupActivity.java
index 78121bc..e9f3baa 100644
--- a/src/com/android/tv/tuner/setup/TunerSetupActivity.java
+++ b/src/com/android/tv/tuner/setup/TunerSetupActivity.java
@@ -19,6 +19,7 @@
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -29,49 +30,98 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.media.tv.TvContract;
+import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.MainThread;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+import android.support.annotation.WorkerThread;
 import android.support.v4.app.NotificationCompat;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.widget.Toast;
 
+import com.android.tv.Features;
 import com.android.tv.TvApplication;
+import com.android.tv.common.AutoCloseableUtils;
+import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.TvCommonConstants;
 import com.android.tv.common.TvCommonUtils;
 import com.android.tv.common.ui.setup.SetupActivity;
 import com.android.tv.common.ui.setup.SetupFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
+import com.android.tv.experiments.Experiments;
 import com.android.tv.tuner.R;
 import com.android.tv.tuner.TunerHal;
 import com.android.tv.tuner.TunerPreferences;
 import com.android.tv.tuner.tvinput.TunerTvInputService;
-import com.android.tv.tuner.util.TunerInputInfoUtils;
+import com.android.tv.tuner.util.PostalCodeUtils;
+
+import java.util.concurrent.Executor;
 
 /**
  * An activity that serves tuner setup process.
  */
 public class TunerSetupActivity extends SetupActivity {
-    private final String TAG = "TunerSetupActivity";
-    // For the recommendation card
+    private static final String TAG = "TunerSetupActivity";
+    private static final boolean DEBUG = false;
+
+    /**
+     * Key for passing tuner type to sub-fragments.
+     */
+    public static final String KEY_TUNER_TYPE = "TunerSetupActivity.tunerType";
+
+    // For the notification.
     private static final String TV_ACTIVITY_CLASS_NAME = "com.android.tv.TvActivity";
+    private static final String TUNER_SET_UP_NOTIFICATION_CHANNEL_ID = "tuner_setup_channel";
     private static final String NOTIFY_TAG = "TunerSetup";
     private static final int NOTIFY_ID = 1000;
     private static final String TAG_DRAWABLE = "drawable";
     private static final String TAG_ICON = "ic_launcher_s";
+    private static final int PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION = 1;
 
     private static final int CHANNEL_MAP_SCAN_FILE[] = {
-            R.raw.ut_us_atsc_center_frequencies_8vsb,
-            R.raw.ut_us_cable_standard_center_frequencies_qam256,
-            R.raw.ut_us_all,
-            R.raw.ut_kr_atsc_center_frequencies_8vsb,
-            R.raw.ut_kr_cable_standard_center_frequencies_qam256,
-            R.raw.ut_kr_all,
-            R.raw.ut_kr_dev_cj_cable_center_frequencies_qam256};
+        R.raw.ut_us_atsc_center_frequencies_8vsb,
+        R.raw.ut_us_cable_standard_center_frequencies_qam256,
+        R.raw.ut_us_all,
+        R.raw.ut_kr_atsc_center_frequencies_8vsb,
+        R.raw.ut_kr_cable_standard_center_frequencies_qam256,
+        R.raw.ut_kr_all,
+        R.raw.ut_kr_dev_cj_cable_center_frequencies_qam256,
+        R.raw.ut_euro_dvbt_all,
+        R.raw.ut_euro_dvbt_all,
+        R.raw.ut_euro_dvbt_all
+    };
 
     private ScanFragment mLastScanFragment;
+    private Integer mTunerType;
+    private TunerHalFactory mTunerHalFactory;
+    private boolean mNeedToShowPostalCodeFragment;
+    private String mPreviousPostalCode;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+        if (DEBUG) Log.d(TAG, "onCreate");
+        new AsyncTask<Void, Void, Integer>() {
+            @Override
+            protected Integer doInBackground(Void... arg0) {
+                return TunerHal.getTunerTypeAndCount(TunerSetupActivity.this).first;
+            }
+
+            @Override
+            protected void onPostExecute(Integer result) {
+                if (!TunerSetupActivity.this.isDestroyed()) {
+                    mTunerType = result;
+                    if (result == null) {
+                        finish();
+                    } else {
+                        showInitialFragment();
+                    }
+                }
+            }
+        }.execute();
         TvApplication.setCurrentRunningProcess(this, false);
         super.onCreate(savedInstanceState);
         // TODO: check {@link shouldShowRequestPermissionRationale}.
@@ -79,16 +129,52 @@
                 != PackageManager.PERMISSION_GRANTED) {
             // No need to check the request result.
             requestPermissions(new String[] {android.Manifest.permission.ACCESS_COARSE_LOCATION},
-                    0);
+                    PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION);
+        }
+        mTunerHalFactory = new TunerHalFactory(getApplicationContext());
+        try {
+            // Updating postal code takes time, therefore we called it here for "warm-up".
+            mPreviousPostalCode = PostalCodeUtils.getLastPostalCode(this);
+            PostalCodeUtils.setLastPostalCode(this, null);
+            PostalCodeUtils.updatePostalCode(this);
+        } catch (Exception e) {
+            // Do nothing. If the last known postal code is null, we'll show guided fragment to
+            // prompt users to input postal code before ConnectionTypeFragment is shown.
+            Log.i(TAG, "Can't get postal code:" + e);
+        }
+    }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+            @NonNull int[] grantResults) {
+        if (requestCode == PERMISSIONS_REQUEST_ACCESS_COARSE_LOCATION) {
+            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED
+                    && Experiments.CLOUD_EPG.get()) {
+                try {
+                    // Updating postal code takes time, therefore we should update postal code
+                    // right after the permission is granted, so that the subsequent operations,
+                    // especially EPG fetcher, could get the newly updated postal code.
+                    PostalCodeUtils.updatePostalCode(this);
+                } catch (Exception e) {
+                    // Do nothing
+                }
+            }
         }
     }
 
     @Override
     protected Fragment onCreateInitialFragment() {
-        SetupFragment fragment = new WelcomeFragment();
-        fragment.setShortDistance(SetupFragment.FRAGMENT_EXIT_TRANSITION
-                | SetupFragment.FRAGMENT_REENTER_TRANSITION);
-        return fragment;
+        if (mTunerType != null) {
+            SetupFragment fragment = new WelcomeFragment();
+            Bundle args = new Bundle();
+            args.putInt(KEY_TUNER_TYPE, mTunerType);
+            fragment.setArguments(args);
+            fragment.setShortDistance(SetupFragment.FRAGMENT_EXIT_TRANSITION
+                    | SetupFragment.FRAGMENT_REENTER_TRANSITION);
+            return fragment;
+        } else {
+            return null;
+        }
     }
 
     @Override
@@ -101,34 +187,42 @@
                         setResult(mLastScanFragment == null ? RESULT_CANCELED : RESULT_OK);
                         finish();
                         break;
-                    default: {
-                        SetupFragment fragment = new ConnectionTypeFragment();
-                        fragment.setShortDistance(SetupFragment.FRAGMENT_ENTER_TRANSITION
-                                | SetupFragment.FRAGMENT_RETURN_TRANSITION);
-                        showFragment(fragment, true);
+                    default:
+                        if (mNeedToShowPostalCodeFragment
+                                || Features.ENABLE_CLOUD_EPG_REGION.isEnabled(
+                                                getApplicationContext())
+                                        && TextUtils.isEmpty(
+                                                PostalCodeUtils.getLastPostalCode(this))) {
+                            // We cannot get postal code automatically. Postal code input fragment
+                            // should always be shown even if users have input some valid postal
+                            // code in this activity before.
+                            mNeedToShowPostalCodeFragment = true;
+                            showPostalCodeFragment();
+                        } else {
+                            showConnectionTypeFragment();
+                        }
                         break;
-                    }
+                }
+                return true;
+            case PostalCodeFragment.ACTION_CATEGORY:
+                if (actionId == SetupMultiPaneFragment.ACTION_DONE
+                        || actionId == SetupMultiPaneFragment.ACTION_SKIP) {
+                    showConnectionTypeFragment();
                 }
                 return true;
             case ConnectionTypeFragment.ACTION_CATEGORY:
-                TunerHal hal = TunerHal.createInstance(getApplicationContext());
-                if (hal == null) {
+                if (mTunerHalFactory.getOrCreate() == null) {
                     finish();
                     Toast.makeText(getApplicationContext(),
                             R.string.ut_channel_scan_tuner_unavailable,Toast.LENGTH_LONG).show();
                     return true;
                 }
-                try {
-                    hal.close();
-                } catch (Exception e) {
-                    Log.e(TAG, "Tuner hal close failed", e);
-                    return true;
-                }
                 mLastScanFragment = new ScanFragment();
-                Bundle args = new Bundle();
-                args.putInt(ScanFragment.EXTRA_FOR_CHANNEL_SCAN_FILE,
+                Bundle args1 = new Bundle();
+                args1.putInt(ScanFragment.EXTRA_FOR_CHANNEL_SCAN_FILE,
                         CHANNEL_MAP_SCAN_FILE[actionId]);
-                mLastScanFragment.setArguments(args);
+                args1.putInt(KEY_TUNER_TYPE, mTunerType);
+                mLastScanFragment.setArguments(args1);
                 showFragment(mLastScanFragment, true);
                 return true;
             case ScanFragment.ACTION_CATEGORY:
@@ -137,7 +231,11 @@
                         getFragmentManager().popBackStack();
                         return true;
                     case ScanFragment.ACTION_FINISH:
+                        mTunerHalFactory.clear();
                         SetupFragment fragment = new ScanResultFragment();
+                        Bundle args2 = new Bundle();
+                        args2.putInt(KEY_TUNER_TYPE, mTunerType);
+                        fragment.setArguments(args2);
                         fragment.setShortDistance(SetupFragment.FRAGMENT_EXIT_TRANSITION
                                 | SetupFragment.FRAGMENT_REENTER_TRANSITION);
                         showFragment(fragment, true);
@@ -183,6 +281,14 @@
         return super.onKeyUp(keyCode, event);
     }
 
+    @Override
+    public void onDestroy() {
+        if (mPreviousPostalCode != null && PostalCodeUtils.getLastPostalCode(this) == null) {
+            PostalCodeUtils.setLastPostalCode(this, mPreviousPostalCode);
+        }
+        super.onDestroy();
+    }
+
     /**
      * A callback to be invoked when the TvInputService is enabled or disabled.
      *
@@ -190,17 +296,17 @@
      * @param enabled {@code true} for the {@link TunerTvInputService} to be enabled;
      *                otherwise {@code false}
      */
-    public static void onTvInputEnabled(Context context, boolean enabled) {
-        // Send a recommendation card for tuner setup if there's no channels and the tuner TV input
+    public static void onTvInputEnabled(Context context, boolean enabled, Integer tunerType) {
+        // Send a notification for tuner setup if there's no channels and the tuner TV input
         // setup has been not done.
         boolean channelScanDoneOnPreference = TunerPreferences.isScanDone(context);
         int channelCountOnPreference = TunerPreferences.getScannedChannelCount(context);
         if (enabled && !channelScanDoneOnPreference && channelCountOnPreference == 0) {
             TunerPreferences.setShouldShowSetupActivity(context, true);
-            sendRecommendationCard(context);
+            sendNotification(context, tunerType);
         } else {
             TunerPreferences.setShouldShowSetupActivity(context, false);
-            cancelRecommendationCard(context);
+            cancelNotification(context);
         }
     }
 
@@ -213,7 +319,7 @@
         String inputId = TvContract.buildInputId(new ComponentName(context.getPackageName(),
                 TunerTvInputService.class.getName()));
 
-        // Make an intent to launch the setup activity of USB tuner TV input.
+        // Make an intent to launch the setup activity of TV tuner input.
         Intent intent = TvCommonUtils.createSetupIntent(
                 new Intent(context, TunerSetupActivity.class), inputId);
         intent.putExtra(TvCommonConstants.EXTRA_INPUT_ID, inputId);
@@ -224,6 +330,27 @@
     }
 
     /**
+     * Gets the currently used tuner HAL.
+     */
+    TunerHal getTunerHal() {
+        return mTunerHalFactory.getOrCreate();
+    }
+
+    /**
+     * Generates tuner HAL.
+     */
+    void generateTunerHal() {
+        mTunerHalFactory.generate();
+    }
+
+    /**
+     * Clears the currently used tuner HAL.
+     */
+    void clearTunerHal() {
+        mTunerHalFactory.clear();
+    }
+
+    /**
      * Returns a {@link PendingIntent} to launch the tuner TV input service.
      *
      * @param context a {@link Context} instance
@@ -233,34 +360,53 @@
                 PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
+    private static void sendNotification(Context context, Integer tunerType) {
+        SoftPreconditions.checkState(tunerType != null, TAG,
+                "tunerType is null when send notification");
+        if (tunerType == null) {
+            return;
+        }
+        Resources resources = context.getResources();
+        String contentTitle = resources.getString(R.string.ut_setup_notification_content_title);
+        int contentTextId = 0;
+        switch (tunerType) {
+            case TunerHal.TUNER_TYPE_BUILT_IN:
+                contentTextId = R.string.bt_setup_notification_content_text;
+                break;
+            case TunerHal.TUNER_TYPE_USB:
+                contentTextId = R.string.ut_setup_notification_content_text;
+                break;
+            case TunerHal.TUNER_TYPE_NETWORK:
+                contentTextId = R.string.nt_setup_notification_content_text;
+                break;
+        }
+        String contentText = resources.getString(contentTextId);
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            sendNotificationInternal(context, contentTitle, contentText);
+        } else {
+            Bitmap largeIcon = BitmapFactory.decodeResource(resources,
+                    R.drawable.recommendation_antenna);
+            sendRecommendationCard(context, contentTitle, contentText, largeIcon);
+        }
+    }
+
     /**
      * Sends the recommendation card to start the tuner TV input setup activity.
      *
      * @param context a {@link Context} instance
      */
-    private static void sendRecommendationCard(Context context) {
-        Resources resources = context.getResources();
-        String focusedTitle = resources.getString(
-                R.string.ut_setup_recommendation_card_focused_title);
-        String title;
-        if (TunerInputInfoUtils.isBuiltInTuner(context)) {
-            title = resources.getString(R.string.bt_setup_recommendation_card_title);
-        } else {
-            title = resources.getString(R.string.ut_setup_recommendation_card_title);
-        }
-        Bitmap largeIcon = BitmapFactory.decodeResource(resources,
-                R.drawable.recommendation_antenna);
-
+    private static void sendRecommendationCard(Context context, String contentTitle,
+            String contentText, Bitmap largeIcon) {
         // Build and send the notification.
         Notification notification = new NotificationCompat.BigPictureStyle(
                 new NotificationCompat.Builder(context)
                         .setAutoCancel(false)
-                        .setContentTitle(focusedTitle)
-                        .setContentText(title)
-                        .setContentInfo(title)
+                        .setContentTitle(contentTitle)
+                        .setContentText(contentText)
+                        .setContentInfo(contentText)
                         .setCategory(Notification.CATEGORY_RECOMMENDATION)
                         .setLargeIcon(largeIcon)
-                        .setSmallIcon(resources.getIdentifier(
+                        .setSmallIcon(context.getResources().getIdentifier(
                                 TAG_ICON, TAG_DRAWABLE, context.getPackageName()))
                         .setContentIntent(createPendingIntentForSetupActivity(context)))
                 .build();
@@ -269,14 +415,129 @@
         notificationManager.notify(NOTIFY_TAG, NOTIFY_ID, notification);
     }
 
+    private static void sendNotificationInternal(Context context, String contentTitle,
+            String contentText) {
+        NotificationManager notificationManager = (NotificationManager) context.getSystemService(
+                Context.NOTIFICATION_SERVICE);
+        notificationManager.createNotificationChannel(new NotificationChannel(
+                TUNER_SET_UP_NOTIFICATION_CHANNEL_ID,
+                context.getResources().getString(R.string.ut_setup_notification_channel_name),
+                NotificationManager.IMPORTANCE_HIGH));
+        Notification notification = new Notification.Builder(
+                context, TUNER_SET_UP_NOTIFICATION_CHANNEL_ID)
+                .setContentTitle(contentTitle)
+                .setContentText(contentText)
+                .setSmallIcon(context.getResources().getIdentifier(
+                        TAG_ICON, TAG_DRAWABLE, context.getPackageName()))
+                .setContentIntent(createPendingIntentForSetupActivity(context))
+                .setVisibility(Notification.VISIBILITY_PUBLIC)
+                .extend(new Notification.TvExtender())
+                .build();
+        notificationManager.notify(NOTIFY_TAG, NOTIFY_ID, notification);
+    }
+
+    private void showPostalCodeFragment() {
+        SetupFragment fragment = new PostalCodeFragment();
+        fragment.setShortDistance(SetupFragment.FRAGMENT_ENTER_TRANSITION
+                | SetupFragment.FRAGMENT_RETURN_TRANSITION);
+        showFragment(fragment, true);
+    }
+
+    private void showConnectionTypeFragment() {
+        SetupFragment fragment = new ConnectionTypeFragment();
+        fragment.setShortDistance(SetupFragment.FRAGMENT_ENTER_TRANSITION
+                | SetupFragment.FRAGMENT_RETURN_TRANSITION);
+        showFragment(fragment, true);
+    }
+
     /**
-     * Cancels the previously shown recommendation card.
+     * Cancels the previously shown notification.
      *
      * @param context a {@link Context} instance
      */
-    public static void cancelRecommendationCard(Context context) {
+    public static void cancelNotification(Context context) {
         NotificationManager notificationManager = (NotificationManager) context
                 .getSystemService(Context.NOTIFICATION_SERVICE);
         notificationManager.cancel(NOTIFY_TAG, NOTIFY_ID);
     }
-}
+
+    @VisibleForTesting
+    static class TunerHalFactory {
+        private Context mContext;
+        @VisibleForTesting
+        TunerHal mTunerHal;
+        private GenerateTunerHalTask mGenerateTunerHalTask;
+        private final Executor mExecutor;
+
+        TunerHalFactory(Context context) {
+            this(context, AsyncTask.SERIAL_EXECUTOR);
+        }
+
+        TunerHalFactory(Context context, Executor executor) {
+            mContext = context;
+            mExecutor = executor;
+        }
+
+        /**
+         * Returns tuner HAL currently used. If it's {@code null} and tuner HAL is not generated
+         * before, tries to generate it synchronously.
+         */
+        @WorkerThread
+        TunerHal getOrCreate() {
+            if (mGenerateTunerHalTask != null
+                    && mGenerateTunerHalTask.getStatus() != AsyncTask.Status.FINISHED) {
+                try {
+                    return mGenerateTunerHalTask.get();
+                } catch (Exception e) {
+                    Log.e(TAG, "Cannot get Tuner HAL: " + e);
+                }
+            } else if (mGenerateTunerHalTask == null && mTunerHal == null) {
+                mTunerHal = createInstance();
+            }
+            return mTunerHal;
+        }
+
+        /**
+         * Generates tuner hal for scanning with asynchronous tasks.
+         */
+        @MainThread
+        void generate() {
+            if (mGenerateTunerHalTask == null && mTunerHal == null) {
+                mGenerateTunerHalTask = new GenerateTunerHalTask();
+                mGenerateTunerHalTask.executeOnExecutor(mExecutor);
+            }
+        }
+
+        /**
+         * Clears the currently used tuner hal.
+         */
+        @MainThread
+        void clear() {
+            if (mGenerateTunerHalTask != null) {
+                mGenerateTunerHalTask.cancel(true);
+                mGenerateTunerHalTask = null;
+            }
+            if (mTunerHal != null) {
+                AutoCloseableUtils.closeQuietly(mTunerHal);
+                mTunerHal = null;
+            }
+        }
+
+        @WorkerThread
+        protected TunerHal createInstance() {
+            return TunerHal.createInstance(mContext);
+        }
+
+        class GenerateTunerHalTask extends AsyncTask<Void, Void, TunerHal> {
+            @Override
+            protected TunerHal doInBackground(Void... args) {
+                return createInstance();
+            }
+
+            @Override
+            protected void onPostExecute(TunerHal tunerHal) {
+                mTunerHal = tunerHal;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/tuner/setup/WelcomeFragment.java b/src/com/android/tv/tuner/setup/WelcomeFragment.java
index 7e80941..feae1ec 100644
--- a/src/com/android/tv/tuner/setup/WelcomeFragment.java
+++ b/src/com/android/tv/tuner/setup/WelcomeFragment.java
@@ -18,18 +18,14 @@
 
 import android.os.Bundle;
 import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
 import android.support.v17.leanback.widget.GuidedAction;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
 import com.android.tv.common.ui.setup.SetupGuidedStepFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.tuner.R;
+import com.android.tv.tuner.TunerHal;
 import com.android.tv.tuner.TunerPreferences;
-import com.android.tv.tuner.util.TunerInputInfoUtils;
-
 import java.util.List;
 
 /**
@@ -41,7 +37,9 @@
 
     @Override
     protected SetupGuidedStepFragment onCreateContentFragment() {
-        return new ContentFragment();
+        ContentFragment fragment = new ContentFragment();
+        fragment.setArguments(getArguments());
+        return fragment;
     }
 
     @Override
@@ -58,11 +56,10 @@
         private int mChannelCountOnPreference;
 
         @Override
-        public View onCreateView(LayoutInflater inflater, ViewGroup container,
-                Bundle savedInstanceState) {
-            mChannelCountOnPreference = TunerPreferences
-                    .getScannedChannelCount(getActivity().getApplicationContext());
-            return super.onCreateView(inflater, container, savedInstanceState);
+        public void onCreate(@Nullable Bundle savedInstanceState) {
+            mChannelCountOnPreference =
+                    TunerPreferences.getScannedChannelCount(getActivity().getApplicationContext());
+            super.onCreate(savedInstanceState);
         }
 
         @NonNull
@@ -70,20 +67,33 @@
         public Guidance onCreateGuidance(Bundle savedInstanceState) {
             String title;
             String description;
+            int tunerType = getArguments().getInt(TunerSetupActivity.KEY_TUNER_TYPE,
+                    TunerHal.TUNER_TYPE_BUILT_IN);
             if (mChannelCountOnPreference == 0) {
-                if (TunerInputInfoUtils.isBuiltInTuner(getActivity())) {
-                    title = getString(R.string.bt_setup_new_title);
-                    description = getString(R.string.bt_setup_new_description);
-                } else {
-                    title = getString(R.string.ut_setup_new_title);
-                    description = getString(R.string.ut_setup_new_description);
+                switch (tunerType) {
+                    case TunerHal.TUNER_TYPE_USB:
+                        title = getString(R.string.ut_setup_new_title);
+                        description = getString(R.string.ut_setup_new_description);
+                        break;
+                    case TunerHal.TUNER_TYPE_NETWORK:
+                        title = getString(R.string.nt_setup_new_title);
+                        description = getString(R.string.nt_setup_new_description);
+                        break;
+                    default:
+                        title = getString(R.string.bt_setup_new_title);
+                        description = getString(R.string.bt_setup_new_description);
                 }
             } else {
                 title = getString(R.string.bt_setup_again_title);
-                if (TunerInputInfoUtils.isBuiltInTuner(getActivity())) {
-                    description = getString(R.string.bt_setup_again_description);
-                } else {
-                    description = getString(R.string.ut_setup_again_description);
+                switch (tunerType) {
+                    case TunerHal.TUNER_TYPE_USB:
+                        description = getString(R.string.ut_setup_again_description);
+                        break;
+                    case TunerHal.TUNER_TYPE_NETWORK:
+                        description = getString(R.string.nt_setup_again_description);
+                        break;
+                    default:
+                        description = getString(R.string.bt_setup_again_description);
                 }
             }
             return new Guidance(title, description, null, null);
diff --git a/src/com/android/tv/tuner/source/FileTsStreamer.java b/src/com/android/tv/tuner/source/FileTsStreamer.java
index 14997ee..f17dd46 100644
--- a/src/com/android/tv/tuner/source/FileTsStreamer.java
+++ b/src/com/android/tv/tuner/source/FileTsStreamer.java
@@ -16,12 +16,14 @@
 
 package com.android.tv.tuner.source;
 
+import android.content.Context;
 import android.os.Environment;
 import android.util.Log;
 import android.util.SparseBooleanArray;
 
 import com.google.android.exoplayer.C;
 import com.google.android.exoplayer.upstream.DataSpec;
+import com.android.tv.Features;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.tuner.ChannelScanFileParser.ScanChannel;
 import com.android.tv.tuner.data.TunerChannel;
@@ -60,6 +62,7 @@
     private final Object mCircularBufferMonitor = new Object();
     private final byte[] mCircularBuffer = new byte[CIRCULAR_BUFFER_SIZE];
     private final FileSourceEventDetector mEventDetector;
+    private final Context mContext;
 
     private long mBytesFetched;
     private long mLastReadPosition;
@@ -120,8 +123,11 @@
      * Creates {@link TsStreamer} for scanning & playing MPEG-2 TS file.
      * @param eventListener the listener for channel & program information
      */
-    public FileTsStreamer(EventDetector.EventListener eventListener) {
-        mEventDetector = new FileSourceEventDetector(eventListener);
+    public FileTsStreamer(EventDetector.EventListener eventListener, Context context) {
+        mEventDetector =
+                new FileSourceEventDetector(
+                        eventListener, Features.ENABLE_FILE_DVB.isEnabled(context));
+        mContext = context;
     }
 
     @Override
@@ -132,8 +138,12 @@
             return false;
         }
         mEventDetector.start(mSource, FileSourceEventDetector.ALL_PROGRAM_NUMBERS);
-        mSource.addPidFilter(TsParser.ATSC_SI_BASE_PID);
         mSource.addPidFilter(TsParser.PAT_PID);
+        mSource.addPidFilter(TsParser.ATSC_SI_BASE_PID);
+        if (Features.ENABLE_FILE_DVB.isEnabled(mContext)) {
+            mSource.addPidFilter(TsParser.DVB_EIT_PID);
+            mSource.addPidFilter(TsParser.DVB_SDT_PID);
+        }
         synchronized (mCircularBufferMonitor) {
             if (mStreaming) {
                 return true;
@@ -160,8 +170,12 @@
             mSource.addPidFilter(i);
         }
         mSource.addPidFilter(channel.getPcrPid());
-        mSource.addPidFilter(TsParser.ATSC_SI_BASE_PID);
         mSource.addPidFilter(TsParser.PAT_PID);
+        mSource.addPidFilter(TsParser.ATSC_SI_BASE_PID);
+        if (Features.ENABLE_FILE_DVB.isEnabled(mContext)) {
+            mSource.addPidFilter(TsParser.DVB_EIT_PID);
+            mSource.addPidFilter(TsParser.DVB_SDT_PID);
+        }
         synchronized (mCircularBufferMonitor) {
             if (mStreaming) {
                 return true;
@@ -256,7 +270,7 @@
          * Returns whether the current pid filter is empty or not.
          */
         public boolean isFilterEmpty() {
-            return mPids.size() > 0;
+            return mPids.size() == 0;
         }
 
         /**
diff --git a/src/com/android/tv/tuner/source/TsDataSourceManager.java b/src/com/android/tv/tuner/source/TsDataSourceManager.java
index ccbb75b..16be758 100644
--- a/src/com/android/tv/tuner/source/TsDataSourceManager.java
+++ b/src/com/android/tv/tuner/source/TsDataSourceManager.java
@@ -17,9 +17,11 @@
 package com.android.tv.tuner.source;
 
 import android.content.Context;
+import android.support.annotation.VisibleForTesting;
 
-import com.android.tv.tuner.data.nano.Channel;
+import com.android.tv.tuner.TunerHal;
 import com.android.tv.tuner.data.TunerChannel;
+import com.android.tv.tuner.data.nano.Channel;
 import com.android.tv.tuner.tvinput.EventDetector;
 
 import java.util.Map;
@@ -31,8 +33,6 @@
  * One TsDataSourceManager should be created for per session.
  */
 public class TsDataSourceManager {
-    private static String TAG = "TsDataSourceManager";
-
     private static final Object sLock = new Object();
     private static final Map<TsDataSource, TsStreamer> sTsStreamers =
             new ConcurrentHashMap<>();
@@ -80,7 +80,7 @@
             if (mIsRecording) {
                 return null;
             }
-            FileTsStreamer streamer = new FileTsStreamer(eventListener);
+            FileTsStreamer streamer = new FileTsStreamer(eventListener, context);
             if (streamer.startStream(channel)) {
                 TsDataSource source = streamer.createDataSource();
                 sTsStreamers.put(source, streamer);
@@ -127,6 +127,14 @@
     }
 
     /**
+     * Add tuner hal into TunerTsStreamerManager for test.
+     */
+    @VisibleForTesting
+    public void addTunerHalForTest(TunerHal tunerHal) {
+        mTunerStreamerManager.addTunerHal(tunerHal, mId);
+    }
+
+    /**
      * Releases persistent resources.
      */
     public void release() {
diff --git a/src/com/android/tv/tuner/source/TunerTsStreamer.java b/src/com/android/tv/tuner/source/TunerTsStreamer.java
index b24048e..843cbdb 100644
--- a/src/com/android/tv/tuner/source/TunerTsStreamer.java
+++ b/src/com/android/tv/tuner/source/TunerTsStreamer.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.util.Log;
+import android.util.Pair;
 
 import com.google.android.exoplayer.C;
 import com.google.android.exoplayer.upstream.DataSpec;
@@ -30,6 +31,7 @@
 import com.android.tv.tuner.tvinput.EventDetector.EventListener;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicLong;
 
@@ -42,23 +44,27 @@
     private static final int MIN_READ_UNIT = 1500;
     private static final int READ_BUFFER_SIZE = MIN_READ_UNIT * 10; // ~15KB
     private static final int CIRCULAR_BUFFER_SIZE = MIN_READ_UNIT * 20000;  // ~ 30MB
+    private static final int TS_PACKET_SIZE = 188;
 
     private static final int READ_TIMEOUT_MS = 5000; // 5 secs.
     private static final int BUFFER_UNDERRUN_SLEEP_MS = 10;
+    private static final int READ_ERROR_STREAMING_ENDED = -1;
+    private static final int READ_ERROR_BUFFER_OVERWRITTEN = -2;
 
     private final Object mCircularBufferMonitor = new Object();
     private final byte[] mCircularBuffer = new byte[CIRCULAR_BUFFER_SIZE];
     private long mBytesFetched;
     private final AtomicLong mLastReadPosition = new AtomicLong();
-    private boolean mEndOfStreamSent;
     private boolean mStreaming;
 
     private final TunerHal mTunerHal;
     private TunerChannel mChannel;
     private Thread mStreamingThread;
     private final EventDetector mEventDetector;
+    private final List<Pair<EventListener, Boolean>> mEventListenerActions = new ArrayList<>();
 
     private final TsStreamWriter mTsStreamWriter;
+    private String mChannelNumber;
 
     public static class TunerDataSource extends TsDataSource {
         private final TunerTsStreamer mTsStreamer;
@@ -103,6 +109,15 @@
                     offset, readLength);
             if (ret > 0) {
                 mLastReadPosition.addAndGet(ret);
+            } else if (ret == READ_ERROR_BUFFER_OVERWRITTEN) {
+                long currentPosition = mStartBufferedPosition + mLastReadPosition.get();
+                long endPosition = mTsStreamer.getBufferedPosition();
+                long diff = ((endPosition - currentPosition + TS_PACKET_SIZE - 1) / TS_PACKET_SIZE)
+                        * TS_PACKET_SIZE;
+                Log.w(TAG, "Demux position jump by overwritten buffer: " + diff);
+                mStartBufferedPosition = currentPosition + diff;
+                mLastReadPosition.set(0);
+                return 0;
             }
             return ret;
         }
@@ -114,7 +129,10 @@
      */
     public TunerTsStreamer(TunerHal tunerHal, EventListener eventListener, Context context) {
         mTunerHal = tunerHal;
-        mEventDetector = new EventDetector(mTunerHal, eventListener);
+        mEventDetector = new EventDetector(mTunerHal);
+        if (eventListener != null) {
+            mEventDetector.registerListener(eventListener);
+        }
         mTsStreamWriter = context != null && TunerPreferences.getStoreTsStream(context) ?
                 new TsStreamWriter(context) : null;
     }
@@ -125,7 +143,8 @@
 
     @Override
     public boolean startStream(TunerChannel channel) {
-        if (mTunerHal.tune(channel.getFrequency(), channel.getModulation())) {
+        if (mTunerHal.tune(channel.getFrequency(), channel.getModulation(),
+                channel.getDisplayNumber(false))) {
             if (channel.hasVideo()) {
                 mTunerHal.addPidFilter(channel.getVideoPid(),
                         TunerHal.FILTER_TYPE_VIDEO);
@@ -148,6 +167,7 @@
                         channel.getProgramNumber());
             }
             mChannel = channel;
+            mChannelNumber = channel.getDisplayNumber();
             synchronized (mCircularBufferMonitor) {
                 if (mStreaming) {
                     Log.w(TAG, "Streaming should be stopped before start streaming");
@@ -156,7 +176,6 @@
                 mStreaming = true;
                 mBytesFetched = 0;
                 mLastReadPosition.set(0L);
-                mEndOfStreamSent = false;
             }
             if (mTsStreamWriter != null) {
                 mTsStreamWriter.setChannel(mChannel);
@@ -172,7 +191,7 @@
 
     @Override
     public boolean startStream(ChannelScanFileParser.ScanChannel channel) {
-        if (mTunerHal.tune(channel.frequency, channel.modulation)) {
+        if (mTunerHal.tune(channel.frequency, channel.modulation, null)) {
             mEventDetector.startDetecting(
                     channel.frequency, channel.modulation, EventDetector.ALL_PROGRAM_NUMBERS);
             synchronized (mCircularBufferMonitor) {
@@ -183,7 +202,6 @@
                 mStreaming = true;
                 mBytesFetched = 0;
                 mLastReadPosition.set(0L);
-                mEndOfStreamSent = false;
             }
             mStreamingThread = new StreamingThread();
             mStreamingThread.start();
@@ -258,6 +276,26 @@
         }
     }
 
+    public String getStreamerInfo() {
+        return "Channel: " + mChannelNumber + ", Streaming: " + mStreaming;
+    }
+
+    public void registerListener(EventListener listener) {
+        if (mEventDetector != null && listener != null) {
+            synchronized (mEventListenerActions) {
+                mEventListenerActions.add(new Pair<>(listener, true));
+            }
+        }
+    }
+
+    public void unregisterListener(EventListener listener) {
+        if (mEventDetector != null) {
+            synchronized (mEventListenerActions) {
+                mEventListenerActions.add(new Pair(listener, false));
+            }
+        }
+    }
+
     private class StreamingThread extends Thread {
         @Override
         public void run() {
@@ -271,6 +309,20 @@
                     }
                 }
 
+                if (mEventDetector != null) {
+                    synchronized (mEventListenerActions) {
+                        for (Pair listenerAction : mEventListenerActions) {
+                            EventListener listener = (EventListener) listenerAction.first;
+                            if ((boolean) listenerAction.second) {
+                                mEventDetector.registerListener(listener);
+                            } else {
+                                mEventDetector.unregisterListener(listener);
+                            }
+                        }
+                        mEventListenerActions.clear();
+                    }
+                }
+
                 int bytesWritten = mTunerHal.readTsStream(dataBuffer, dataBuffer.length);
                 if (bytesWritten <= 0) {
                     try {
@@ -321,21 +373,14 @@
      * @throws IOException
      */
     public int readAt(long pos, byte[] buffer, int offset, int amount) throws IOException {
-        long readStartTime = System.currentTimeMillis();
         while (true) {
             synchronized (mCircularBufferMonitor) {
-                if (mEndOfStreamSent || !mStreaming) {
-                    return -1;
+                if (!mStreaming) {
+                    return READ_ERROR_STREAMING_ENDED;
                 }
                 if (mBytesFetched - CIRCULAR_BUFFER_SIZE > pos) {
-                    Log.e(TAG, "Demux is requesting the data which is already overwritten.");
-                    return -1;
-                }
-                if (System.currentTimeMillis() - readStartTime > READ_TIMEOUT_MS) {
-                    // Nothing was received during READ_TIMEOUT_MS before.
-                    mEndOfStreamSent = true;
-                    mCircularBufferMonitor.notifyAll();
-                    return -1;
+                    Log.w(TAG, "Demux is requesting the data which is already overwritten.");
+                    return READ_ERROR_BUFFER_OVERWRITTEN;
                 }
                 if (mBytesFetched < pos + amount) {
                     try {
diff --git a/src/com/android/tv/tuner/source/TunerTsStreamerManager.java b/src/com/android/tv/tuner/source/TunerTsStreamerManager.java
index cf1f6dc..258a4d8 100644
--- a/src/com/android/tv/tuner/source/TunerTsStreamerManager.java
+++ b/src/com/android/tv/tuner/source/TunerTsStreamerManager.java
@@ -42,6 +42,7 @@
     private final Object mCancelLock = new Object();
     private final StreamerFinder mStreamerFinder = new StreamerFinder();
     private final Map<Integer, TsStreamerCreator> mCreators = new HashMap<>();
+    private final Map<Integer, EventDetector.EventListener> mListeners = new HashMap<>();
     private final Map<TsDataSource, TunerTsStreamer> mSourceToStreamerMap = new HashMap<>();
     private final TunerHalManager mTunerHalManager = new TunerHalManager();
     private static TunerTsStreamerManager sInstance;
@@ -68,6 +69,8 @@
                 mStreamerFinder.appendSessionLocked(channel, sessionId);
                 TunerTsStreamer streamer =  mStreamerFinder.getStreamerLocked(channel);
                 TsDataSource source = streamer.createDataSource();
+                mListeners.put(sessionId, listener);
+                streamer.registerListener(listener);
                 mSourceToStreamerMap.put(source, streamer);
                 return source;
             }
@@ -83,6 +86,7 @@
             if (!creator.isCancelledLocked()) {
                 mStreamerFinder.putLocked(channel, sessionId, streamer);
                 TsDataSource source = streamer.createDataSource();
+                mListeners.put(sessionId, listener);
                 mSourceToStreamerMap.put(source, streamer);
                 return source;
             }
@@ -104,6 +108,8 @@
             if (streamer == null) {
                 return;
             }
+            EventDetector.EventListener listener = mListeners.remove(sessionId);
+            streamer.unregisterListener(listener);
             TunerChannel channel = streamer.getChannel();
             SoftPreconditions.checkState(channel != null);
             mStreamerFinder.removeSessionLocked(channel, sessionId);
@@ -125,6 +131,13 @@
         }
     }
 
+    /**
+     * Add tuner hal into TunerHalManager for test.
+     */
+    void addTunerHal(TunerHal tunerHal, int sessionId) {
+        mTunerHalManager.addTunerHal(tunerHal, sessionId);
+    }
+
     synchronized void release(int sessionId) {
         mTunerHalManager.releaseCachedHal(sessionId);
     }
@@ -261,16 +274,16 @@
         }
 
         private void releaseTunerHal(TunerHal hal, int sessionId, boolean reuse) {
-            if (!reuse) {
+            if (!reuse || !hal.isReusable()) {
                 AutoCloseableUtils.closeQuietly(hal);
                 return;
             }
             TunerHal cachedHal = mTunerHals.get(sessionId);
             if (cachedHal != hal) {
                 mTunerHals.put(sessionId, hal);
-            }
-            if (cachedHal != null && cachedHal != hal) {
-                AutoCloseableUtils.closeQuietly(cachedHal);
+                if (cachedHal != null) {
+                    AutoCloseableUtils.closeQuietly(cachedHal);
+                }
             }
         }
 
@@ -283,5 +296,9 @@
                 AutoCloseableUtils.closeQuietly(hal);
             }
         }
+
+        private void addTunerHal(TunerHal tunerHal, int sessionId) {
+            mTunerHals.put(sessionId, tunerHal);
+        }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/tv/tuner/ts/SectionParser.java b/src/com/android/tv/tuner/ts/SectionParser.java
index 8c1f6a1..e1f890f 100644
--- a/src/com/android/tv/tuner/ts/SectionParser.java
+++ b/src/com/android/tv/tuner/ts/SectionParser.java
@@ -18,11 +18,12 @@
 
 import android.media.tv.TvContentRating;
 import android.media.tv.TvContract.Programs.Genres;
+import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
 
-import com.android.tv.tuner.data.nano.Channel;
 import com.android.tv.tuner.data.PsiData.PatItem;
 import com.android.tv.tuner.data.PsiData.PmtItem;
 import com.android.tv.tuner.data.PsipData.Ac3AudioDescriptor;
@@ -34,24 +35,32 @@
 import com.android.tv.tuner.data.PsipData.GenreDescriptor;
 import com.android.tv.tuner.data.PsipData.Iso639LanguageDescriptor;
 import com.android.tv.tuner.data.PsipData.MgtItem;
+import com.android.tv.tuner.data.PsipData.ParentalRatingDescriptor;
 import com.android.tv.tuner.data.PsipData.PsipSection;
 import com.android.tv.tuner.data.PsipData.RatingRegion;
 import com.android.tv.tuner.data.PsipData.RegionalRating;
+import com.android.tv.tuner.data.PsipData.SdtItem;
+import com.android.tv.tuner.data.PsipData.ServiceDescriptor;
+import com.android.tv.tuner.data.PsipData.ShortEventDescriptor;
 import com.android.tv.tuner.data.PsipData.TsDescriptor;
 import com.android.tv.tuner.data.PsipData.VctItem;
+import com.android.tv.tuner.data.nano.Channel;
 import com.android.tv.tuner.data.nano.Track.AtscAudioTrack;
 import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import com.android.tv.tuner.util.ByteArrayBuffer;
 
+import com.android.tv.tuner.util.ConvertUtils;
 import com.ibm.icu.text.UnicodeDecompressor;
 
 import java.io.UnsupportedEncodingException;
 import java.nio.charset.Charset;
+import java.util.Calendar;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Parses ATSC PSIP sections.
@@ -68,6 +77,13 @@
     private static final byte TABLE_ID_EIT = (byte) 0xcb;
     private static final byte TABLE_ID_ETT = (byte) 0xcc;
 
+    // Table id for DVB
+    private static final byte TABLE_ID_SDT = (byte) 0x42;
+    private static final byte TABLE_ID_DVB_ACTUAL_P_F_EIT = (byte) 0x4e;
+    private static final byte TABLE_ID_DVB_OTHER_P_F_EIT = (byte) 0x4f;
+    private static final byte TABLE_ID_DVB_ACTUAL_SCHEDULE_EIT = (byte) 0x50;
+    private static final byte TABLE_ID_DVB_OTHER_SCHEDULE_EIT = (byte) 0x60;
+
     // For details of the structure for the tags of descriptors, see ATSC A/65 Table 6.25.
     public static final int DESCRIPTOR_TAG_ISO639LANGUAGE = 0x0a;
     public static final int DESCRIPTOR_TAG_CAPTION_SERVICE = 0x86;
@@ -76,6 +92,12 @@
     public static final int DESCRIPTOR_TAG_EXTENDED_CHANNEL_NAME = 0xa0;
     public static final int DESCRIPTOR_TAG_GENRE = 0xab;
 
+    // For details of the structure for the tags of DVB descriptors, see DVB Document A038 Table 12.
+    public static final int DVB_DESCRIPTOR_TAG_SERVICE = 0x48;
+    public static final int DVB_DESCRIPTOR_TAG_SHORT_EVENT = 0X4d;
+    public static final int DVB_DESCRIPTOR_TAG_CONTENT = 0x54;
+    public static final int DVB_DESCRIPTOR_TAG_PARENTAL_RATING = 0x55;
+
     private static final byte COMPRESSION_TYPE_NO_COMPRESSION = (byte) 0x00;
     private static final byte MODE_SELECTED_UNICODE_RANGE_1 = (byte) 0x00;  // 0x0000 - 0x00ff
     private static final byte MODE_UTF16 = (byte) 0x3f;
@@ -88,17 +110,57 @@
 
     // The following values are defined in the live channels app.
     // See https://developer.android.com/reference/android/media/tv/TvContentRating.html.
+    private static final String RATING_DOMAIN = "com.android.tv";
     private static final String RATING_REGION_RATING_SYSTEM_US_TV = "US_TV";
+    private static final String RATING_REGION_RATING_SYSTEM_US_MV = "US_MV";
     private static final String RATING_REGION_RATING_SYSTEM_KR_TV = "KR_TV";
 
     private static final String[] RATING_REGION_TABLE_US_TV = {
         "US_TV_Y", "US_TV_Y7", "US_TV_G", "US_TV_PG", "US_TV_14", "US_TV_MA"
     };
 
+    private static final String[] RATING_REGION_TABLE_US_MV = {
+        "US_MV_G", "US_MV_PG", "US_MV_PG13", "US_MV_R", "US_MV_NC17"
+    };
+
     private static final String[] RATING_REGION_TABLE_KR_TV = {
         "KR_TV_ALL", "KR_TV_7", "KR_TV_12", "KR_TV_15", "KR_TV_19"
     };
 
+    private static final String[] RATING_REGION_TABLE_US_TV_SUBRATING = {
+        "US_TV_D", "US_TV_L", "US_TV_S", "US_TV_V", "US_TV_FV"
+    };
+
+    // According to ANSI-CEA-766-D
+    private static final int VALUE_US_TV_Y = 1;
+    private static final int VALUE_US_TV_Y7 = 2;
+    private static final int VALUE_US_TV_NONE = 1;
+    private static final int VALUE_US_TV_G = 2;
+    private static final int VALUE_US_TV_PG = 3;
+    private static final int VALUE_US_TV_14 = 4;
+    private static final int VALUE_US_TV_MA = 5;
+
+    private static final int DIMENSION_US_TV_RATING = 0;
+    private static final int DIMENSION_US_TV_D = 1;
+    private static final int DIMENSION_US_TV_L = 2;
+    private static final int DIMENSION_US_TV_S = 3;
+    private static final int DIMENSION_US_TV_V = 4;
+    private static final int DIMENSION_US_TV_Y = 5;
+    private static final int DIMENSION_US_TV_FV = 6;
+    private static final int DIMENSION_US_MV_RATING = 7;
+
+    private static final int VALUE_US_MV_G = 2;
+    private static final int VALUE_US_MV_PG = 3;
+    private static final int VALUE_US_MV_PG13 = 4;
+    private static final int VALUE_US_MV_R = 5;
+    private static final int VALUE_US_MV_NC17 = 6;
+    private static final int VALUE_US_MV_X = 7;
+
+    private static final String STRING_US_TV_Y = "US_TV_Y";
+    private static final String STRING_US_TV_Y7 = "US_TV_Y7";
+    private static final String STRING_US_TV_FV = "US_TV_FV";
+
+
     /*
      * The following CRC table is from the code generated by the following command.
      * $ python pycrc.py --model crc-32-mpeg --algorithm table-driven --generate c
@@ -330,6 +392,7 @@
         void onVctParsed(List<VctItem> items, int sectionNumber, int lastSectionNumber);
         void onEitParsed(int sourceId, List<EitItem> items);
         void onEttParsed(int sourceId, List<EttItem> descriptions);
+        void onSdtParsed(List<SdtItem> items);
     }
 
     private final OutputListener mListener;
@@ -367,6 +430,10 @@
         mParsedEttItems.clear();
     }
 
+    public void resetVersionNumbers() {
+        mSectionVersionMap.clear();
+    }
+
     private void parseSection(byte[] data) {
         if (!checkSanity(data)) {
             Log.d(TAG, "Bad CRC!");
@@ -410,6 +477,13 @@
             case TABLE_ID_ETT:
                 result = parseETT(data);
                 break;
+            case TABLE_ID_SDT:
+                result = parseSDT(data);
+                break;
+            case TABLE_ID_DVB_ACTUAL_P_F_EIT:
+            case TABLE_ID_DVB_ACTUAL_SCHEDULE_EIT:
+                result = parseDVBEIT(data);
+                break;
             default:
                 break;
         }
@@ -510,10 +584,8 @@
             pos += 11 + descriptorsLength;
             results.add(new MgtItem(tableType, tableTypePid));
         }
-        if ((data[pos] & 0xf0) != 0xf0) {
-            Log.e(TAG, "Broken MGT.");
-            return false;
-        }
+        // Skip the remaining descriptor part which we don't use.
+
         if (mListener != null) {
             mListener.onMgtParsed(results);
         }
@@ -704,6 +776,127 @@
         return true;
     }
 
+    private boolean parseSDT(byte[] data) {
+        // For details of the structure for SDT, see DVB Document A038 Table 5.
+        if (DEBUG) {
+            Log.d(TAG, "SDT id discovered");
+        }
+        if (data.length <= 11) {
+            Log.e(TAG, "Broken SDT.");
+            return false;
+        }
+        if ((data[1] & 0x80) >> 7 != 1) {
+            Log.e(TAG, "Broken SDT, section syntax indicator error.");
+            return false;
+        }
+        int sectionLength = ((data[1] & 0x0f) << 8) | (data[2] & 0xff);
+        int transportStreamId = ((data[3] & 0xff) << 8) | (data[4] & 0xff);
+        int originalNetworkId = ((data[8] & 0xff) << 8) | (data[9] & 0xff);
+        int pos = 11;
+        if (sectionLength + 3 > data.length) {
+            Log.e(TAG, "Broken SDT.");
+        }
+        List<SdtItem> sdtItems = new ArrayList<>();
+        while (pos + 9 < data.length) {
+            int serviceId = ((data[pos] & 0xff) << 8) | (data[pos + 1] & 0xff);
+            int descriptorsLength = ((data[pos + 3] & 0x0f) << 8) | (data[pos + 4] & 0xff);
+            pos += 5;
+            List<TsDescriptor> descriptors = parseDescriptors(data, pos, pos + descriptorsLength);
+            List<ServiceDescriptor> serviceDescriptors = generateServiceDescriptors(descriptors);
+            String serviceName = "";
+            String serviceProviderName = "";
+            int serviceType = 0;
+            for (ServiceDescriptor serviceDescriptor : serviceDescriptors) {
+                serviceName = serviceDescriptor.getServiceName();
+                serviceProviderName = serviceDescriptor.getServiceProviderName();
+                serviceType = serviceDescriptor.getServiceType();
+            }
+            if (serviceDescriptors.size() > 0) {
+                sdtItems.add(new SdtItem(serviceName, serviceProviderName, serviceType, serviceId,
+                        originalNetworkId));
+            }
+            pos += descriptorsLength;
+        }
+        if (mListener != null) {
+            mListener.onSdtParsed(sdtItems);
+        }
+        return true;
+    }
+
+    private boolean parseDVBEIT(byte[] data) {
+        // For details of the structure for DVB ETT, see DVB Document A038 Table 7.
+        if (DEBUG) {
+            Log.d(TAG, "DVB EIT is discovered.");
+        }
+        if (data.length < 18) {
+            Log.e(TAG, "Broken DVB EIT.");
+            return false;
+        }
+        int sectionLength = ((data[1] & 0x0f) << 8) | (data[2] & 0xff);
+        int sourceId = ((data[3] & 0xff) << 8) | (data[4] & 0xff);
+        int transportStreamId = ((data[8] & 0xff) << 8) | (data[9] & 0xff);
+        int originalNetworkId = ((data[10] & 0xff) << 8) | (data[11] & 0xff);
+
+        int pos = 14;
+        List<EitItem> results = new ArrayList<>();
+        while (pos + 12 < data.length) {
+            int eventId = ((data[pos] & 0xff) << 8) + (data[pos + 1] & 0xff);
+            float modifiedJulianDate = ((data[pos + 2] &  0xff) << 8) | (data[pos + 3] & 0xff);
+            int startYear = (int) ((modifiedJulianDate - 15078.2f) / 365.25f);
+            int mjdMonth = (int) ((modifiedJulianDate - 14956.1f
+                    - (int) (startYear * 365.25f)) / 30.6001f);
+            int startDay = (int) modifiedJulianDate - 14956 - (int) (startYear * 365.25f)
+                    - (int) (mjdMonth * 30.6001f);
+            int startMonth = mjdMonth - 1;
+            if (mjdMonth == 14 || mjdMonth == 15) {
+                startYear += 1;
+                startMonth -= 12;
+            }
+            int startHour = ((data[pos + 4] & 0xf0) >> 4) * 10 + (data[pos + 4] & 0x0f);
+            int startMinute = ((data[pos + 5] & 0xf0) >> 4) * 10 + (data[pos + 5] & 0x0f);
+            int startSecond = ((data[pos + 6] & 0xf0) >> 4) * 10 + (data[pos + 6] & 0x0f);
+            Calendar calendar = Calendar.getInstance();
+            startYear += 1900;
+            calendar.set(startYear, startMonth, startDay, startHour, startMinute, startSecond);
+            long startTime = ConvertUtils.convertUnixEpochToGPSTime(
+                    calendar.getTimeInMillis() / 1000);
+            int durationInSecond = (((data[pos + 7] & 0xf0) >> 4) * 10
+                    + (data[pos + 7] & 0x0f)) * 3600
+                    + (((data[pos + 8] & 0xf0) >> 4) * 10 + (data[pos + 8] & 0x0f)) * 60
+                    + (((data[pos + 9] & 0xf0) >> 4) * 10 + (data[pos + 9] & 0x0f));
+            int descriptorsLength = ((data[pos + 10] & 0x0f) << 8)
+                    | (data[pos + 10 + 1] & 0xff);
+            int descriptorsPos = pos + 10 + 2;
+            if (data.length < descriptorsPos + descriptorsLength) {
+                Log.e(TAG, "Broken EIT.");
+                return false;
+            }
+            List<TsDescriptor> descriptors = parseDescriptors(
+                    data, descriptorsPos, descriptorsPos + descriptorsLength);
+            if (DEBUG) {
+                Log.d(TAG, String.format("DVB EIT descriptors size: %d", descriptors.size()));
+            }
+            // TODO: Add logic to generating content rating for dvb. See DVB document 6.2.28 for
+            // details. Content rating here will be null
+            String contentRating = generateContentRating(descriptors);
+            // TODO: Add logic for generating genre for dvb. See DVB document 6.2.9 for details.
+            // Genre here will be null here.
+            String broadcastGenre = generateBroadcastGenre(descriptors);
+            String canonicalGenre = generateCanonicalGenre(descriptors);
+            String titleText = generateShortEventName(descriptors);
+            List<AtscAudioTrack> audioTracks = generateAudioTracks(descriptors);
+            List<AtscCaptionTrack> captionTracks = generateCaptionTracks(descriptors);
+            pos += 12 + descriptorsLength;
+            results.add(new EitItem(EitItem.INVALID_PROGRAM_ID, eventId, titleText,
+                    startTime, durationInSecond, contentRating, audioTracks, captionTracks,
+                    broadcastGenre, canonicalGenre, null));
+        }
+        if (mListener != null) {
+            mListener.onEitParsed(sourceId, results);
+        }
+        return true;
+    }
+
     private static List<AtscAudioTrack> generateAudioTracks(List<TsDescriptor> descriptors) {
         // The list of audio tracks sent is located at both AC3 Audio descriptor and ISO 639
         // Language descriptor.
@@ -717,6 +910,9 @@
                 if (audioDescriptor.getLanguage() != null) {
                     audioTrack.language = audioDescriptor.getLanguage();
                 }
+                if (audioTrack.language == null) {
+                    audioTrack.language = "";
+                }
                 audioTrack.audioType = AtscAudioTrack.AUDIOTYPE_UNDEFINED;
                 audioTrack.channelCount = audioDescriptor.getNumChannels();
                 audioTrack.sampleRate = audioDescriptor.getSampleRate();
@@ -787,46 +983,181 @@
         return services;
     }
 
-    private static String generateContentRating(List<TsDescriptor> descriptors) {
-        List<String> contentRatings = new ArrayList<>();
-        for (TsDescriptor descriptor : descriptors) {
-            if (descriptor instanceof ContentAdvisoryDescriptor) {
-                ContentAdvisoryDescriptor contentAdvisoryDescriptor =
-                        (ContentAdvisoryDescriptor) descriptor;
-                for (RatingRegion ratingRegion : contentAdvisoryDescriptor.getRatingRegions()) {
-                    for (RegionalRating index : ratingRegion.getRegionalRatings()) {
-                        String ratingSystem = null;
-                        String rating = null;
-                        switch (ratingRegion.getName()) {
-                            case RATING_REGION_US_TV:
-                                ratingSystem = RATING_REGION_RATING_SYSTEM_US_TV;
-                                if (index.getDimension() == 0 && index.getRating() >= 0
-                                        && index.getRating() < RATING_REGION_TABLE_US_TV.length) {
-                                    rating = RATING_REGION_TABLE_US_TV[index.getRating()];
-                                }
-                                break;
-                            case RATING_REGION_KR_TV:
-                                ratingSystem = RATING_REGION_RATING_SYSTEM_KR_TV;
-                                if (index.getDimension() == 0 && index.getRating() >= 0
-                                        && index.getRating() < RATING_REGION_TABLE_KR_TV.length) {
-                                    rating = RATING_REGION_TABLE_KR_TV[index.getRating()];
-                                }
-                                break;
-                            default:
-                                break;
-                        }
-                        if (ratingSystem != null && rating != null) {
-                            contentRatings.add(TvContentRating
-                                    .createRating("com.android.tv", ratingSystem, rating)
-                                    .flattenToString());
-                        }
-                    }
-                }
+    @VisibleForTesting
+    static String generateContentRating(List<TsDescriptor> descriptors) {
+        Set<String> contentRatings = new ArraySet<>();
+        List<RatingRegion> usRatingRegions = getRatingRegions(descriptors, RATING_REGION_US_TV);
+        List<RatingRegion> krRatingRegions = getRatingRegions(descriptors, RATING_REGION_KR_TV);
+        for (RatingRegion region : usRatingRegions) {
+            String contentRating = getUsRating(region);
+            if (contentRating != null) {
+                contentRatings.add(contentRating);
+            }
+        }
+        for (RatingRegion region : krRatingRegions) {
+            String contentRating = getKrRating(region);
+            if (contentRating != null) {
+                contentRatings.add(contentRating);
             }
         }
         return TextUtils.join(",", contentRatings);
     }
 
+    /**
+     * Gets a list of {@link RatingRegion} in the specific region.
+     *
+     * @param descriptors {@link TsDescriptor} list which may contains rating information
+     * @param region the specific region
+     * @return a list of {@link RatingRegion} in the specific region
+     */
+    private static List<RatingRegion> getRatingRegions(List<TsDescriptor> descriptors, int region) {
+        List<RatingRegion> ratingRegions = new ArrayList<>();
+        for (TsDescriptor descriptor : descriptors) {
+            if (!(descriptor instanceof ContentAdvisoryDescriptor)) {
+                continue;
+            }
+            ContentAdvisoryDescriptor contentAdvisoryDescriptor =
+                    (ContentAdvisoryDescriptor) descriptor;
+            for (RatingRegion ratingRegion : contentAdvisoryDescriptor.getRatingRegions()) {
+                if (ratingRegion.getName() == region) {
+                    ratingRegions.add(ratingRegion);
+                }
+            }
+        }
+        return ratingRegions;
+    }
+
+    /**
+     * Gets US content rating and subratings (if any).
+     *
+     * @param ratingRegion a {@link RatingRegion} instance which may contain rating information.
+     * @return A string representing the US content rating and subratings. The format of the string
+     *     is defined in {@link TvContentRating}. null, if no such a string exists.
+     */
+    private static String getUsRating(RatingRegion ratingRegion) {
+        if (ratingRegion.getName() != RATING_REGION_US_TV) {
+            return null;
+        }
+        List<RegionalRating> regionalRatings = ratingRegion.getRegionalRatings();
+        String rating = null;
+        int ratingIndex = VALUE_US_TV_NONE;
+        List<String> subratings = new ArrayList<>();
+        for (RegionalRating index : regionalRatings) {
+            // See Table 3 of ANSI-CEA-766-D
+            int dimension = index.getDimension();
+            int value = index.getRating();
+            switch (dimension) {
+                    // According to Table 6.27 of ATSC A65,
+                    // the dimensions shall be in increasing order.
+                    // Therefore, rating and ratingIndex are assigned before any corresponding
+                    // subrating.
+                case DIMENSION_US_TV_RATING:
+                    if (value >= VALUE_US_TV_G && value < RATING_REGION_TABLE_US_TV.length) {
+                        rating = RATING_REGION_TABLE_US_TV[value];
+                        ratingIndex = value;
+                    }
+                    break;
+                case DIMENSION_US_TV_D:
+                    if (value == 1
+                            && (ratingIndex == VALUE_US_TV_PG || ratingIndex == VALUE_US_TV_14)) {
+                        // US_TV_D is applicable to US_TV_PG and US_TV_14
+                        subratings.add(RATING_REGION_TABLE_US_TV_SUBRATING[dimension - 1]);
+                    }
+                    break;
+                case DIMENSION_US_TV_L:
+                case DIMENSION_US_TV_S:
+                case DIMENSION_US_TV_V:
+                    if (value == 1
+                            && ratingIndex >= VALUE_US_TV_PG
+                            && ratingIndex <= VALUE_US_TV_MA) {
+                        // US_TV_L, US_TV_S, and US_TV_V are applicable to
+                        // US_TV_PG, US_TV_14 and US_TV_MA
+                        subratings.add(RATING_REGION_TABLE_US_TV_SUBRATING[dimension - 1]);
+                    }
+                    break;
+                case DIMENSION_US_TV_Y:
+                    if (rating == null) {
+                        if (value == VALUE_US_TV_Y) {
+                            rating = STRING_US_TV_Y;
+                        } else if (value == VALUE_US_TV_Y7) {
+                            rating = STRING_US_TV_Y7;
+                        }
+                    }
+                    break;
+                case DIMENSION_US_TV_FV:
+                    if (STRING_US_TV_Y7.equals(rating) && value == 1) {
+                        // US_TV_FV is applicable to US_TV_Y7
+                        subratings.add(STRING_US_TV_FV);
+                    }
+                    break;
+                case DIMENSION_US_MV_RATING:
+                    if (value >= VALUE_US_MV_G && value <= VALUE_US_MV_X) {
+                        if (value == VALUE_US_MV_X) {
+                            // US_MV_X was replaced by US_MV_NC17 in 1990,
+                            // and it's not supported by TvContentRating
+                            value = VALUE_US_MV_NC17;
+                        }
+                        if (rating != null) {
+                            // According to Table 3 of ANSI-CEA-766-D,
+                            // DIMENSION_US_TV_RATING and DIMENSION_US_MV_RATING shall not be
+                            // present in the same descriptor.
+                            Log.w(
+                                    TAG,
+                                    "DIMENSION_US_TV_RATING and DIMENSION_US_MV_RATING are "
+                                            + "present in the same descriptor");
+                        } else {
+                            return TvContentRating.createRating(
+                                            RATING_DOMAIN,
+                                            RATING_REGION_RATING_SYSTEM_US_MV,
+                                            RATING_REGION_TABLE_US_MV[value - 2])
+                                    .flattenToString();
+                        }
+                    }
+                    break;
+
+                default:
+                    break;
+            }
+        }
+        if (rating == null) {
+            return null;
+        }
+
+        String[] subratingArray = subratings.toArray(new String[subratings.size()]);
+        return TvContentRating.createRating(
+                        RATING_DOMAIN, RATING_REGION_RATING_SYSTEM_US_TV, rating, subratingArray)
+                .flattenToString();
+    }
+
+    /**
+     * Gets KR(South Korea) content rating.
+     *
+     * @param ratingRegion a {@link RatingRegion} instance which may contain rating information.
+     * @return A string representing the KR content rating. The format of the string is defined in
+     *     {@link TvContentRating}. null, if no such a string exists.
+     */
+    private static String getKrRating(RatingRegion ratingRegion) {
+        if (ratingRegion.getName() != RATING_REGION_KR_TV) {
+            return null;
+        }
+        List<RegionalRating> regionalRatings = ratingRegion.getRegionalRatings();
+        String rating = null;
+        for (RegionalRating index : regionalRatings) {
+            if (index.getDimension() == 0
+                    && index.getRating() >= 0
+                    && index.getRating() < RATING_REGION_TABLE_KR_TV.length) {
+                rating = RATING_REGION_TABLE_KR_TV[index.getRating()];
+                break;
+            }
+        }
+        if (rating == null) {
+            return null;
+        }
+        return TvContentRating.createRating(
+                        RATING_DOMAIN, RATING_REGION_RATING_SYSTEM_KR_TV, rating)
+                .flattenToString();
+    }
+
     private static String generateBroadcastGenre(List<TsDescriptor> descriptors) {
         for (TsDescriptor descriptor : descriptors) {
             if (descriptor instanceof GenreDescriptor) {
@@ -849,6 +1180,28 @@
         return null;
     }
 
+    private static List<ServiceDescriptor> generateServiceDescriptors(
+            List<TsDescriptor> descriptors) {
+        List<ServiceDescriptor> serviceDescriptors = new ArrayList<>();
+        for (TsDescriptor descriptor : descriptors) {
+            if (descriptor instanceof ServiceDescriptor) {
+                ServiceDescriptor serviceDescriptor = (ServiceDescriptor) descriptor;
+                serviceDescriptors.add(serviceDescriptor);
+            }
+        }
+        return serviceDescriptors;
+    }
+
+    private static String generateShortEventName(List<TsDescriptor> descriptors) {
+        for (TsDescriptor descriptor : descriptors) {
+            if (descriptor instanceof ShortEventDescriptor) {
+                ShortEventDescriptor shortEventDescriptor = (ShortEventDescriptor) descriptor;
+                return shortEventDescriptor.getEventName();
+            }
+        }
+        return "";
+    }
+
     private static List<TsDescriptor> parseDescriptors(byte[] data, int offset, int limit) {
         // For details of the structure for descriptors, see ATSC A/65 Section 6.9.
         List<TsDescriptor> descriptors = new ArrayList<>();
@@ -894,6 +1247,22 @@
                     descriptor = parseIso639Language(data, pos, pos + length + 2);
                     break;
 
+                case DVB_DESCRIPTOR_TAG_SERVICE:
+                    descriptor = parseDvbService(data, pos, pos + length + 2);
+                    break;
+
+                case DVB_DESCRIPTOR_TAG_SHORT_EVENT:
+                    descriptor = parseDvbShortEvent(data, pos, pos + length + 2);
+                    break;
+
+                case DVB_DESCRIPTOR_TAG_CONTENT:
+                    descriptor = parseDvbContent(data, pos, pos + length + 2);
+                    break;
+
+                case DVB_DESCRIPTOR_TAG_PARENTAL_RATING:
+                    descriptor = parseDvbParentalRating(data, pos, pos + length + 2);
+                    break;
+
                 default:
             }
             if (descriptor != null) {
@@ -948,6 +1317,7 @@
             pos += 3;
             boolean ccType = (data[pos] & 0x80) != 0;
             if (!ccType) {
+                pos +=3;
                 continue;
             }
             int captionServiceNumber = data[pos] & 0x3f;
@@ -987,6 +1357,7 @@
             int ratingRegion = data[pos] & 0xff;
             int dimensionCount = data[pos + 1] & 0xff;
             pos += 2;
+            int previousDimension = -1;
             for (int j = 0; j < dimensionCount; ++j) {
                 if (limit <= pos + 1) {
                     Log.e(TAG, "Broken ContentAdvisory");
@@ -994,6 +1365,13 @@
                 }
                 int dimensionIndex = data[pos] & 0xff;
                 int ratingValue = data[pos + 1] & 0x0f;
+                if (dimensionIndex <= previousDimension) {
+                    // According to Table 6.27 of ATSC A65,
+                    // the indices shall be in increasing order.
+                    Log.e(TAG, "Broken ContentAdvisory");
+                    return null;
+                }
+                previousDimension = dimensionIndex;
                 pos += 2;
                 indices.add(new RegionalRating(dimensionIndex, ratingValue));
             }
@@ -1189,6 +1567,74 @@
                 language, language2);
     }
 
+    private static TsDescriptor parseDvbService(byte[] data, int pos, int limit) {
+        // For details of DVB service descriptors, see DVB Document A038 Table 86.
+        if (limit < pos + 5) {
+            Log.e(TAG, "Broken service descriptor.");
+            return null;
+        }
+        pos += 2;
+        int serviceType = data[pos] & 0xff;
+        pos++;
+        int serviceProviderNameLength = data[pos] & 0xff;
+        pos++;
+        String serviceProviderName = extractTextFromDvb(data, pos, serviceProviderNameLength);
+        pos += serviceProviderNameLength;
+        int serviceNameLength = data[pos] & 0xff;
+        pos++;
+        String serviceName = extractTextFromDvb(data, pos, serviceNameLength);
+        return new ServiceDescriptor(serviceType, serviceProviderName, serviceName);
+    }
+
+    private static TsDescriptor parseDvbShortEvent(byte[] data, int pos, int limit) {
+        // For details of DVB service descriptors, see DVB Document A038 Table 91.
+        if (limit < pos + 7) {
+            Log.e(TAG, "Broken short event descriptor.");
+            return null;
+        }
+        pos += 2;
+        String language = new String(data, pos, 3);
+        int eventNameLength = data[pos + 3] & 0xff;
+        pos += 4;
+        if (pos + eventNameLength > limit) {
+            Log.e(TAG, "Broken short event descriptor.");
+            return null;
+        }
+        String eventName = new String(data, pos, eventNameLength);
+        pos += eventNameLength;
+        int textLength = data[pos] & 0xff;
+        if (pos + textLength > limit) {
+            Log.e(TAG, "Broken short event descriptor.");
+            return null;
+        }
+        pos++;
+        String text = new String(data, pos, textLength);
+        return new ShortEventDescriptor(language, eventName, text);
+    }
+
+    private static TsDescriptor parseDvbContent(byte[] data, int pos, int limit) {
+        // TODO: According to DVB Document A038 Table 27 to add a parser for content descriptor to
+        // get content genre.
+        return null;
+    }
+
+    private static TsDescriptor parseDvbParentalRating(byte[] data, int pos, int limit) {
+        // For details of DVB service descriptors, see DVB Document A038 Table 81.
+        HashMap<String, Integer> ratings = new HashMap<>();
+        pos += 2;
+        while (pos + 4 <= limit) {
+            String countryCode = new String(data, pos, 3);
+            int rating = data[pos + 3] & 0xff;
+            pos += 4;
+            if (rating > 15) {
+                // Rating > 15 means that the ratings is defined by broadcaster.
+                continue;
+            }
+            ratings.put(countryCode, rating + 3);
+        }
+        return new ParentalRatingDescriptor(ratings);
+    }
+
     private static int getShortNameSize(byte[] data, int offset) {
         for (int i = 0; i < MAX_SHORT_NAME_BYTES; i += 2) {
             if (data[offset + i] == 0 && data[offset + i + 1] == 0) {
@@ -1244,6 +1690,55 @@
         return null;
     }
 
+    private static String extractTextFromDvb(byte[] data, int pos, int length) {
+        // For details of DVB character set selection, see DVB Document A038 Annex A.
+        if (data.length < pos + length) {
+            return null;
+        }
+        try {
+            String charsetPrefix = "ISO-8859-";
+            switch (data[0]) {
+                case 0x01:
+                case 0x02:
+                case 0x03:
+                case 0x04:
+                case 0x05:
+                case 0x06:
+                case 0x07:
+                case 0x09:
+                case 0x0A:
+                case 0x0B:
+                    String charset = charsetPrefix + String.valueOf(data[0] & 0xff + 4);
+                    return new String(data, pos, length, charset);
+                case 0x10:
+                    if (length < 3) {
+                        Log.e(TAG, "Broken DVB text");
+                        return null;
+                    }
+                    int codeTable = data[pos + 2] & 0xff;
+                    if (data[pos + 1] == 0 && codeTable > 0 && codeTable < 15) {
+                        return new String(
+                                data, pos, length, charsetPrefix + String.valueOf(codeTable));
+                    } else {
+                        return new String(data, pos, length, "ISO-8859-1");
+                    }
+                case 0x11:
+                case 0x14:
+                case 0x15:
+                    return new String(data, pos, length, "UTF-16BE");
+                case 0x12:
+                    return new String(data, pos, length, "EUC-KR");
+                case 0x13:
+                    return new String(data, pos, length, "GB2312");
+                default:
+                    return new String(data, pos, length, "ISO-8859-1");
+            }
+        } catch (UnsupportedEncodingException e) {
+            Log.e(TAG, "Unsupported text format.", e);
+        }
+        return new String(data, pos, length);
+    }
+
     private static boolean checkSanity(byte[] data) {
         if (data.length <= 1) {
             return false;
diff --git a/src/com/android/tv/tuner/ts/TsParser.java b/src/com/android/tv/tuner/ts/TsParser.java
index c24c2a2..7cdb534 100644
--- a/src/com/android/tv/tuner/ts/TsParser.java
+++ b/src/com/android/tv/tuner/ts/TsParser.java
@@ -25,6 +25,7 @@
 import com.android.tv.tuner.data.PsipData.EitItem;
 import com.android.tv.tuner.data.PsipData.EttItem;
 import com.android.tv.tuner.data.PsipData.MgtItem;
+import com.android.tv.tuner.data.PsipData.SdtItem;
 import com.android.tv.tuner.data.PsipData.VctItem;
 import com.android.tv.tuner.data.TunerChannel;
 import com.android.tv.tuner.ts.SectionParser.OutputListener;
@@ -46,6 +47,8 @@
 
     public static final int ATSC_SI_BASE_PID = 0x1ffb;
     public static final int PAT_PID = 0x0000;
+    public static final int DVB_SDT_PID = 0x0011;
+    public static final int DVB_EIT_PID = 0x0012;
     private static final int TS_PACKET_START_CODE = 0x47;
     private static final int TS_PACKET_TEI_MASK = 0x80;
     private static final int TS_PACKET_SIZE = 188;
@@ -64,6 +67,7 @@
     private final Map<Integer, VctItem> mProgramNumberToVctItemMap = new HashMap<>();
     private final Map<Integer, List<PmtItem>> mProgramNumberToPMTMap = new HashMap<>();
     private final Map<Integer, List<EitItem>> mSourceIdToEitMap = new HashMap<>();
+    private final Map<Integer, SdtItem> mProgramNumberToSdtItemMap = new HashMap<>();
     private final Map<EventSourceEntry, List<EitItem>> mEitMap = new HashMap<>();
     private final Map<EventSourceEntry, List<EttItem>> mETTMap = new HashMap<>();
     private final TreeSet<Integer> mEITPids = new TreeSet<>();
@@ -71,6 +75,7 @@
     private final SparseBooleanArray mProgramNumberHandledStatus = new SparseBooleanArray();
     private final SparseBooleanArray mVctItemHandledStatus = new SparseBooleanArray();
     private final TsOutputListener mListener;
+    private final boolean mIsDvbSignal;
 
     private int mVctItemCount;
     private int mHandledVctItemCount;
@@ -84,6 +89,7 @@
         void onEitItemParsed(VctItem channel, List<EitItem> items);
         void onEttPidDetected(int pid);
         void onAllVctItemsParsed();
+        void onSdtItemParsed(SdtItem channel, List<PmtItem> pmtItems);
     }
 
     private abstract class Stream {
@@ -102,6 +108,7 @@
         }
 
         protected abstract void handleData(byte[] data, boolean startIndicator);
+        protected abstract void resetDataVersions();
     }
 
     private class SectionStream extends Stream {
@@ -138,6 +145,11 @@
             mSectionParser.parseSections(mPacket);
         }
 
+        @Override
+        protected void resetDataVersions() {
+            mSectionParser.resetVersionNumbers();
+        }
+
         private final OutputListener mSectionListener = new OutputListener() {
             @Override
             public void onPatParsed(List<PatItem> items) {
@@ -173,6 +185,12 @@
                             mListener.onAllVctItemsParsed();
                         }
                     }
+                    SdtItem sdtItem = mProgramNumberToSdtItemMap.get(programNumber);
+                    if (sdtItem != null) {
+                        // When PMT is parsed later than SDT.
+                        mProgramNumberHandledStatus.put(programNumber, true);
+                        handleSdtItem(sdtItem, items);
+                    }
                 }
             }
 
@@ -276,6 +294,24 @@
                 mETTMap.put(entry, descriptions);
                 handleEvents(sourceId);
             }
+
+            @Override
+            public void onSdtParsed(List<SdtItem> sdtItems) {
+                for (SdtItem sdtItem : sdtItems) {
+                    if (DEBUG) Log.d(TAG, "onSdtParsed " + sdtItem);
+                    int programNumber = sdtItem.getServiceId();
+                    mProgramNumberToSdtItemMap.put(programNumber, sdtItem);
+                    List<PmtItem> pmtList = mProgramNumberToPMTMap.get(programNumber);
+                    if (pmtList != null) {
+                        mProgramNumberHandledStatus.put(programNumber, true);
+                        handleSdtItem(sdtItem, pmtList);
+                    } else {
+                        mProgramNumberHandledStatus.put(programNumber, false);
+                        Log.i(TAG, "onSdtParsed, but PMT for programNo " + programNumber
+                                + " is not found yet.");
+                    }
+                }
+            }
         };
     }
 
@@ -335,6 +371,15 @@
         }
     }
 
+    private void handleSdtItem(SdtItem channel, List<PmtItem> pmtItems) {
+        if (DEBUG) {
+            Log.d(TAG, "handleSdtItem " + channel);
+        }
+        if (mListener != null) {
+            mListener.onSdtItemParsed(channel, pmtItems);
+        }
+    }
+
     private void handleEvents(int sourceId) {
         Map<Integer, EitItem> itemSet = new HashMap<>();
         for (int pid : mEITPids) {
@@ -367,17 +412,26 @@
             handleEitItems(channel, items);
         } else {
             mVctItemHandledStatus.put(sourceId, false);
-            Log.i(TAG, "onEITParsed, but VCT for sourceId " + sourceId + " is not found yet.");
+            if (!mIsDvbSignal) {
+                // Log only when zapping to non-DVB channels, since there is not VCT in DVB signal.
+                Log.i(TAG, "onEITParsed, but VCT for sourceId " + sourceId + " is not found yet.");
+            }
         }
     }
 
     /**
      * Creates MPEG-2 TS parser.
+     *
      * @param listener TsOutputListener
      */
-    public TsParser(TsOutputListener listener) {
-        startListening(ATSC_SI_BASE_PID);
+    public TsParser(TsOutputListener listener, boolean isDvbSignal) {
         startListening(PAT_PID);
+        startListening(ATSC_SI_BASE_PID);
+        mIsDvbSignal = isDvbSignal;
+        if (isDvbSignal) {
+            startListening(DVB_EIT_PID);
+            startListening(DVB_SDT_PID);
+        }
         mListener = listener;
     }
 
@@ -412,7 +466,7 @@
             // We are not interested in this packet.
             return false;
         }
-        if (payloadPos > pos + TS_PACKET_SIZE) {
+        if (payloadPos >= pos + TS_PACKET_SIZE) {
             if (DEBUG) Log.d(TAG, "Payload should be included in a single TS packet.");
             return false;
         }
@@ -451,4 +505,16 @@
         }
         return incompleteChannels;
     }
+
+    /**
+     * Reset the versions so that data with old version number can be handled.
+     */
+    public void resetDataVersions() {
+        for (int eitPid : mEITPids) {
+            Stream stream = mStreamMap.get(eitPid);
+            if (stream != null) {
+                stream.resetDataVersions();
+            }
+        }
+    }
 }
diff --git a/src/com/android/tv/tuner/tvinput/ChannelDataManager.java b/src/com/android/tv/tuner/tvinput/ChannelDataManager.java
index a16bc52..d2b4998 100644
--- a/src/com/android/tv/tuner/tvinput/ChannelDataManager.java
+++ b/src/com/android/tv/tuner/tvinput/ChannelDataManager.java
@@ -25,6 +25,7 @@
 import android.database.Cursor;
 import android.media.tv.TvContract;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
@@ -37,6 +38,7 @@
 import com.android.tv.tuner.data.PsipData.EitItem;
 import com.android.tv.tuner.data.TunerChannel;
 import com.android.tv.tuner.util.ConvertUtils;
+import com.android.tv.util.PermissionUtils;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -192,11 +194,14 @@
 
     public void release() {
         mHandler.removeCallbacksAndMessages(null);
-        mHandlerThread.quitSafely();
+        releaseSafely();
     }
 
     public void releaseSafely() {
         mHandlerThread.quitSafely();
+        mListener = null;
+        mChannelScanListener = null;
+        mChannelScanHandler = null;
     }
 
     public TunerChannel getChannel(long channelId) {
@@ -435,7 +440,7 @@
                     }
                 }
                 ops.add(buildContentProviderOperation(ContentProviderOperation.newInsert(
-                        TvContract.Programs.CONTENT_URI), newItem, channel.getChannelId()));
+                        TvContract.Programs.CONTENT_URI), newItem, channel));
                 if (ops.size() >= BATCH_OPERATION_COUNT) {
                     applyBatch(channel.getName(), ops);
                     ops.clear();
@@ -505,7 +510,7 @@
                 continue;
             }
             ops.add(buildContentProviderOperation(ContentProviderOperation.newInsert(
-                    TvContract.Programs.CONTENT_URI), item, channel.getChannelId()));
+                    TvContract.Programs.CONTENT_URI), item, channel));
             if (ops.size() >= BATCH_OPERATION_COUNT) {
                 applyBatch(channel.getName(), ops);
                 ops.clear();
@@ -516,9 +521,13 @@
     }
 
     private ContentProviderOperation buildContentProviderOperation(
-            ContentProviderOperation.Builder builder, EitItem item, Long channelId) {
-        if (channelId != null) {
-            builder.withValue(TvContract.Programs.COLUMN_CHANNEL_ID, channelId);
+            ContentProviderOperation.Builder builder, EitItem item, TunerChannel channel) {
+        if (channel != null) {
+            builder.withValue(TvContract.Programs.COLUMN_CHANNEL_ID, channel.getChannelId());
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                builder.withValue(TvContract.Programs.COLUMN_RECORDING_PROHIBITED,
+                        channel.isRecordingProhibited() ? 1 : 0);
+            }
         }
         if (item != null) {
             builder.withValue(TvContract.Programs.COLUMN_TITLE, item.getTitleText())
@@ -556,7 +565,10 @@
         values.put(TvContract.Channels.COLUMN_DISPLAY_NAME, channel.getName());
         values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_DATA, channel.toByteArray());
         values.put(TvContract.Channels.COLUMN_DESCRIPTION, channel.getDescription());
+        values.put(TvContract.Channels.COLUMN_VIDEO_FORMAT, channel.getVideoFormat());
         values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_FLAG1, VERSION);
+        values.put(TvContract.Channels.COLUMN_INTERNAL_PROVIDER_FLAG2,
+                channel.isRecordingProhibited() ? 1 : 0);
 
         if (channelId <= 0) {
             values.put(TvContract.Channels.COLUMN_INPUT_ID, mInputId);
@@ -598,13 +610,29 @@
     }
 
     private void checkVersion() {
-        String selection = TvContract.Channels.COLUMN_INTERNAL_PROVIDER_FLAG1 + "<>?";
-        try (Cursor cursor = mContext.getContentResolver().query(mChannelsUri,
-                CHANNEL_DATA_SELECTION_ARGS, selection,
-                new String[] {Integer.toString(VERSION)}, null)) {
-            if (cursor != null && cursor.moveToFirst()) {
-                // The stored channel data seem outdated. Delete them all.
-                clearChannels();
+        if (PermissionUtils.hasAccessAllEpg(mContext)) {
+            String selection = TvContract.Channels.COLUMN_INTERNAL_PROVIDER_FLAG1 + "<>?";
+            try (Cursor cursor = mContext.getContentResolver().query(mChannelsUri,
+                    CHANNEL_DATA_SELECTION_ARGS, selection,
+                    new String[] {Integer.toString(VERSION)}, null)) {
+                if (cursor != null && cursor.moveToFirst()) {
+                    // The stored channel data seem outdated. Delete them all.
+                    clearChannels();
+                }
+            }
+        } else {
+            try (Cursor cursor = mContext.getContentResolver().query(mChannelsUri,
+                    new String[] { TvContract.Channels.COLUMN_INTERNAL_PROVIDER_FLAG1 },
+                    null, null, null)) {
+                if (cursor != null) {
+                    while (cursor.moveToNext()) {
+                        int version = cursor.getInt(0);
+                        if (version != VERSION) {
+                            clearChannels();
+                            break;
+                        }
+                    }
+                }
             }
         }
     }
diff --git a/src/com/android/tv/tuner/tvinput/EventDetector.java b/src/com/android/tv/tuner/tvinput/EventDetector.java
index a132398..dc99118 100644
--- a/src/com/android/tv/tuner/tvinput/EventDetector.java
+++ b/src/com/android/tv/tuner/tvinput/EventDetector.java
@@ -21,12 +21,12 @@
 import android.util.SparseBooleanArray;
 
 import com.android.tv.tuner.TunerHal;
-import com.android.tv.tuner.data.nano.Track.AtscAudioTrack;
-import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
-import com.android.tv.tuner.data.TunerChannel;
 import com.android.tv.tuner.ts.TsParser;
 import com.android.tv.tuner.data.PsiData;
 import com.android.tv.tuner.data.PsipData;
+import com.android.tv.tuner.data.TunerChannel;
+import com.android.tv.tuner.data.nano.Track.AtscAudioTrack;
+import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -48,10 +48,11 @@
 
     // To prevent channel duplication
     private final Set<Integer> mVctProgramNumberSet = new HashSet<>();
+    private final Set<Integer> mSdtProgramNumberSet = new HashSet<>();
     private final SparseArray<TunerChannel> mChannelMap = new SparseArray<>();
     private final SparseBooleanArray mVctCaptionTracksFound = new SparseBooleanArray();
     private final SparseBooleanArray mEitCaptionTracksFound = new SparseBooleanArray();
-    private final EventListener mEventListener;
+    private final List<EventListener> mEventListeners = new ArrayList<>();
     private int mFrequency;
     private String mModulation;
     private int mProgramNumber = ALL_PROGRAM_NUMBERS;
@@ -105,8 +106,10 @@
                     item.setHasCaptionTrack();
                 }
             }
-            if (tunerChannel != null && mEventListener != null) {
-                mEventListener.onEventDetected(tunerChannel, items);
+            if (tunerChannel != null && !mEventListeners.isEmpty()) {
+                for (EventListener eventListener : mEventListeners) {
+                    eventListener.onEventDetected(tunerChannel, items);
+                }
             }
         }
 
@@ -117,8 +120,10 @@
 
         @Override
         public void onAllVctItemsParsed() {
-            if (mEventListener != null) {
-                mEventListener.onChannelScanDone();
+            if (!mEventListeners.isEmpty()) {
+                for (EventListener eventListener : mEventListeners) {
+                    eventListener.onChannelScanDone();
+                }
             }
         }
 
@@ -161,8 +166,47 @@
             if (!found) {
                 mVctProgramNumberSet.add(channelProgramNumber);
             }
-            if (mEventListener != null) {
-                mEventListener.onChannelDetected(tunerChannel, !found);
+            if (!mEventListeners.isEmpty()) {
+                for (EventListener eventListener : mEventListeners) {
+                    eventListener.onChannelDetected(tunerChannel, !found);
+                }
+            }
+        }
+
+        @Override
+        public void onSdtItemParsed(PsipData.SdtItem channel, List<PsiData.PmtItem> pmtItems) {
+            if (DEBUG) {
+                Log.d(TAG, "onSdtItemParsed SDT " + channel);
+                Log.d(TAG, "                PMT " + pmtItems);
+            }
+
+            // Merges the audio and caption tracks located in PMT items into the tracks of the given
+            // tuner channel.
+            TunerChannel tunerChannel = new TunerChannel(channel, pmtItems);
+            List<AtscAudioTrack> audioTracks = new ArrayList<>();
+            List<AtscCaptionTrack> captionTracks = new ArrayList<>();
+            for (PsiData.PmtItem pmtItem : pmtItems) {
+                if (pmtItem.getAudioTracks() != null) {
+                    audioTracks.addAll(pmtItem.getAudioTracks());
+                }
+                if (pmtItem.getCaptionTracks() != null) {
+                    captionTracks.addAll(pmtItem.getCaptionTracks());
+                }
+            }
+            int channelProgramNumber = channel.getServiceId();
+            tunerChannel.setAudioTracks(audioTracks);
+            tunerChannel.setCaptionTracks(captionTracks);
+            tunerChannel.setFrequency(mFrequency);
+            tunerChannel.setModulation(mModulation);
+            mChannelMap.put(tunerChannel.getProgramNumber(), tunerChannel);
+            boolean found = mSdtProgramNumberSet.contains(channelProgramNumber);
+            if (!found) {
+                mSdtProgramNumberSet.add(channelProgramNumber);
+            }
+            if (!mEventListeners.isEmpty()) {
+                for (EventListener eventListener : mEventListeners) {
+                    eventListener.onChannelDetected(tunerChannel, !found);
+                }
             }
         }
     };
@@ -196,18 +240,23 @@
 
     /**
      * Creates a detector for ATSC TV channles and program information.
+     *
      * @param usbTunerInteface {@link TunerHal}
-     * @param listener for ATSC TV channels and program information
      */
-    public EventDetector(TunerHal usbTunerInteface, EventListener listener) {
+    public EventDetector(TunerHal usbTunerInteface) {
         mTunerHal = usbTunerInteface;
-        mEventListener = listener;
     }
 
     private void reset() {
-        mTsParser = new TsParser(mTsOutputListener); // TODO: Use TsParser.reset()
+        // TODO: Use TsParser.reset()
+        int deliverySystemType = mTunerHal.getDeliverySystemType();
+        mTsParser =
+                new TsParser(
+                        mTsOutputListener,
+                        TunerHal.isDvbDeliverySystem(mTunerHal.getDeliverySystemType()));
         mPidSet.clear();
         mVctProgramNumberSet.clear();
+        mSdtProgramNumberSet.clear();
         mVctCaptionTracksFound.clear();
         mEitCaptionTracksFound.clear();
         mChannelMap.clear();
@@ -258,4 +307,28 @@
     public List<TunerChannel> getMalFormedChannels() {
         return mTsParser.getMalFormedChannels();
     }
+
+    /**
+     * Registers an EventListener.
+     * @param eventListener the listener to be registered
+     */
+    public void registerListener(EventListener eventListener) {
+        if (mTsParser != null) {
+            // Resets the version numbers so that the new listener can receive the EIT items.
+            // Otherwise, each EIT session is handled only once unless there is a new version.
+            mTsParser.resetDataVersions();
+        }
+        mEventListeners.add(eventListener);
+    }
+
+    /**
+     * Unregisters an EventListener.
+     * @param eventListener the listener to be unregistered
+     */
+    public void unregisterListener(EventListener eventListener) {
+        boolean removed = mEventListeners.remove(eventListener);
+        if (!removed && DEBUG) {
+            Log.d(TAG, "Cannot unregister a non-registered listener!");
+        }
+    }
 }
diff --git a/src/com/android/tv/tuner/tvinput/FileSourceEventDetector.java b/src/com/android/tv/tuner/tvinput/FileSourceEventDetector.java
index 61de24f..99222bf 100644
--- a/src/com/android/tv/tuner/tvinput/FileSourceEventDetector.java
+++ b/src/com/android/tv/tuner/tvinput/FileSourceEventDetector.java
@@ -23,10 +23,11 @@
 import com.android.tv.tuner.data.PsiData.PatItem;
 import com.android.tv.tuner.data.PsiData.PmtItem;
 import com.android.tv.tuner.data.PsipData.EitItem;
+import com.android.tv.tuner.data.PsipData.SdtItem;
 import com.android.tv.tuner.data.PsipData.VctItem;
+import com.android.tv.tuner.data.TunerChannel;
 import com.android.tv.tuner.data.nano.Track.AtscAudioTrack;
 import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
-import com.android.tv.tuner.data.TunerChannel;
 import com.android.tv.tuner.source.FileTsStreamer;
 import com.android.tv.tuner.ts.TsParser;
 import com.android.tv.tuner.tvinput.EventDetector.EventListener;
@@ -49,15 +50,18 @@
 
     private TsParser mTsParser;
     private final Set<Integer> mVctProgramNumberSet = new HashSet<>();
+    private final Set<Integer> mSdtProgramNumberSet = new HashSet<>();
     private final SparseArray<TunerChannel> mChannelMap = new SparseArray<>();
     private final SparseBooleanArray mVctCaptionTracksFound = new SparseBooleanArray();
     private final SparseBooleanArray mEitCaptionTracksFound = new SparseBooleanArray();
     private final EventListener mEventListener;
+    private final boolean mEnableDvbSignal;
     private FileTsStreamer.StreamProvider mStreamProvider;
     private int mProgramNumber = ALL_PROGRAM_NUMBERS;
 
-    public FileSourceEventDetector(EventDetector.EventListener listener) {
+    public FileSourceEventDetector(EventDetector.EventListener listener, boolean enableDvbSignal) {
         mEventListener = listener;
+        mEnableDvbSignal = enableDvbSignal;
     }
 
     /**
@@ -74,9 +78,10 @@
     }
 
     private void reset() {
-        mTsParser = new TsParser(mTsOutputListener); // TODO: Use TsParser.reset()
+        mTsParser = new TsParser(mTsOutputListener, mEnableDvbSignal); // TODO: Use TsParser.reset()
         mStreamProvider.clearPidFilter();
         mVctProgramNumberSet.clear();
+        mSdtProgramNumberSet.clear();
         mVctCaptionTracksFound.clear();
         mEitCaptionTracksFound.clear();
         mChannelMap.clear();
@@ -206,5 +211,39 @@
                 mEventListener.onChannelDetected(tunerChannel, !found);
             }
         }
+
+        @Override
+        public void onSdtItemParsed(SdtItem channel, List<PmtItem> pmtItems) {
+            if (DEBUG) {
+                Log.d(TAG, "onSdtItemParsed SDT " + channel);
+                Log.d(TAG, "                PMT " + pmtItems);
+            }
+
+            // Merges the audio and caption tracks located in PMT items into the tracks of the given
+            // tuner channel.
+            TunerChannel tunerChannel = TunerChannel.forDvbFile(channel, pmtItems);
+            List<AtscAudioTrack> audioTracks = new ArrayList<>();
+            List<AtscCaptionTrack> captionTracks = new ArrayList<>();
+            for (PmtItem pmtItem : pmtItems) {
+                if (pmtItem.getAudioTracks() != null) {
+                    audioTracks.addAll(pmtItem.getAudioTracks());
+                }
+                if (pmtItem.getCaptionTracks() != null) {
+                    captionTracks.addAll(pmtItem.getCaptionTracks());
+                }
+            }
+            int channelProgramNumber = channel.getServiceId();
+            tunerChannel.setFilepath(mStreamProvider.getFilepath());
+            tunerChannel.setAudioTracks(audioTracks);
+            tunerChannel.setCaptionTracks(captionTracks);
+            mChannelMap.put(tunerChannel.getProgramNumber(), tunerChannel);
+            boolean found = mSdtProgramNumberSet.contains(channelProgramNumber);
+            if (!found) {
+                mSdtProgramNumberSet.add(channelProgramNumber);
+            }
+            if (mEventListener != null) {
+                mEventListener.onChannelDetected(tunerChannel, !found);
+            }
+        }
     };
 }
diff --git a/src/com/android/tv/tuner/tvinput/TunerDebug.java b/src/com/android/tv/tuner/tvinput/TunerDebug.java
index a7a41ea..2ddc946 100644
--- a/src/com/android/tv/tuner/tvinput/TunerDebug.java
+++ b/src/com/android/tv/tuner/tvinput/TunerDebug.java
@@ -55,10 +55,10 @@
         return LazyHolder.INSTANCE;
     }
 
-    public static void notifyVideoFrameDrop(long delta) {
+    public static void notifyVideoFrameDrop(int count, long delta) {
         // TODO: provide timestamp mismatch information using delta
         TunerDebug sTunerDebug = getInstance();
-        sTunerDebug.mVideoFrameDrop++;
+        sTunerDebug.mVideoFrameDrop += count;
     }
 
     public static int getVideoFrameDrop() {
diff --git a/src/com/android/tv/tuner/tvinput/TunerRecordingSessionWorker.java b/src/com/android/tv/tuner/tvinput/TunerRecordingSessionWorker.java
index 6ec55e4..34013bf 100644
--- a/src/com/android/tv/tuner/tvinput/TunerRecordingSessionWorker.java
+++ b/src/com/android/tv/tuner/tvinput/TunerRecordingSessionWorker.java
@@ -33,14 +33,18 @@
 import android.support.annotation.Nullable;
 import android.util.Log;
 
+import android.util.Pair;
+import com.google.android.exoplayer.C;
 import com.android.tv.TvApplication;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.recording.RecordingCapability;
 import com.android.tv.dvr.DvrStorageStatusManager;
-import com.android.tv.dvr.RecordedProgram;
+import com.android.tv.dvr.data.RecordedProgram;
 import com.android.tv.tuner.DvbDeviceAccessor;
 import com.android.tv.tuner.data.PsipData;
+import com.android.tv.tuner.data.PsipData.EitItem;
 import com.android.tv.tuner.data.TunerChannel;
+import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import com.android.tv.tuner.exoplayer.ExoPlayerSampleExtractor;
 import com.android.tv.tuner.exoplayer.SampleExtractor;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
@@ -53,10 +57,10 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Random;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -71,6 +75,7 @@
     private static final String SORT_BY_TIME = TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS
             + ", " + TvContract.Programs.COLUMN_CHANNEL_ID + ", "
             + TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS;
+    private static final long TUNING_RETRY_INTERVAL_MS = TimeUnit.SECONDS.toMillis(4);
     private static final long STORAGE_MONITOR_INTERVAL_MS = TimeUnit.SECONDS.toMillis(4);
     private static final long MIN_PARTIAL_RECORDING_DURATION_MS = TimeUnit.SECONDS.toMillis(10);
     private static final long PREPARE_RECORDER_POLL_MS = 50;
@@ -80,20 +85,23 @@
     private static final int MSG_STOP_RECORDING = 4;
     private static final int MSG_MONITOR_STORAGE_STATUS = 5;
     private static final int MSG_RELEASE = 6;
+    private static final int MSG_UPDATE_CC_INFO = 7;
     private final RecordingCapability mCapabilities;
 
     public RecordingCapability getCapabilities() {
         return mCapabilities;
     }
 
-    @IntDef({STATE_IDLE, STATE_TUNED, STATE_RECORDING})
+    @IntDef({STATE_IDLE, STATE_TUNING, STATE_TUNED, STATE_RECORDING})
     @Retention(RetentionPolicy.SOURCE)
     public @interface DvrSessionState {}
     private static final int STATE_IDLE = 1;
-    private static final int STATE_TUNED = 2;
-    private static final int STATE_RECORDING = 3;
+    private static final int STATE_TUNING = 2;
+    private static final int STATE_TUNED = 3;
+    private static final int STATE_RECORDING = 4;
 
     private static final long CHANNEL_ID_NONE = -1;
+    private static final int MAX_TUNING_RETRY = 6;
 
     private final Context mContext;
     private final ChannelDataManager mChannelDataManager;
@@ -108,13 +116,16 @@
     private long mRecordStartTime;
     private long mRecordEndTime;
     private boolean mRecorderRunning;
-    private BufferManager mBufferManager;
     private SampleExtractor mRecorder;
     private final TunerRecordingSession mSession;
     @DvrSessionState private int mSessionState = STATE_IDLE;
     private final String mInputId;
     private Uri mProgramUri;
 
+    private PsipData.EitItem mCurrenProgram;
+    private List<AtscCaptionTrack> mCaptionTracks;
+    private DvrStorageManager mDvrStorageManager;
+
     public TunerRecordingSessionWorker(Context context, String inputId,
             ChannelDataManager dataManager, TunerRecordingSession session) {
         mRandom.setSeed(System.nanoTime());
@@ -157,6 +168,7 @@
         if (mChannel == null || mChannel.compareTo(channel) != 0) {
             return;
         }
+        mHandler.obtainMessage(MSG_UPDATE_CC_INFO, new Pair<>(channel, items)).sendToTarget();
         mChannelDataManager.notifyEventDetected(channel, items);
     }
 
@@ -178,7 +190,7 @@
     @MainThread
     public void tune(Uri channelUri) {
         mHandler.removeCallbacksAndMessages(null);
-        mHandler.obtainMessage(MSG_TUNE, channelUri).sendToTarget();
+        mHandler.obtainMessage(MSG_TUNE, 0, 0, channelUri).sendToTarget();
     }
 
     /**
@@ -211,11 +223,22 @@
         switch (msg.what) {
             case MSG_TUNE: {
                 Uri channelUri = (Uri) msg.obj;
+                int retryCount = msg.arg1;
                 if (DEBUG) Log.d(TAG, "Tune to " + channelUri);
                 if (doTune(channelUri)) {
-                    mSession.onTuned(channelUri);
-                } else {
-                    reset();
+                    if (mSessionState == STATE_TUNED) {
+                        mSession.onTuned(channelUri);
+                    } else {
+                        Log.w(TAG, "Tuner stream cannot be created due to resource shortage.");
+                        if (retryCount < MAX_TUNING_RETRY) {
+                            Message tuneMsg =
+                                    mHandler.obtainMessage(MSG_TUNE, retryCount + 1, 0, channelUri);
+                            mHandler.sendMessageDelayed(tuneMsg, TUNING_RETRY_INTERVAL_MS);
+                        } else {
+                            mSession.onError(TvInputManager.RECORDING_ERROR_RESOURCE_BUSY);
+                            reset();
+                        }
+                    }
                 }
                 return true;
             }
@@ -281,6 +304,12 @@
                 mHandler.getLooper().quitSafely();
                 return true;
             }
+            case MSG_UPDATE_CC_INFO: {
+                Pair<TunerChannel, List<EitItem>> pair =
+                        (Pair<TunerChannel, List<EitItem>>) msg.obj;
+                updateCaptionTracks(pair.first, pair.second);
+                return true;
+            }
         }
         return false;
     }
@@ -310,20 +339,17 @@
             mRecorder.release();
             mRecorder = null;
         }
-        if (mBufferManager != null) {
-            mBufferManager.close();
-            mBufferManager = null;
-        }
         if (mTunerSource != null) {
             mSourceManager.releaseDataSource(mTunerSource);
             mTunerSource = null;
         }
+        mDvrStorageManager = null;
         mSessionState = STATE_IDLE;
         mRecorderRunning = false;
     }
 
     private boolean doTune(Uri channelUri) {
-        if (mSessionState != STATE_IDLE) {
+        if (mSessionState != STATE_IDLE && mSessionState != STATE_TUNING) {
             mSession.onError(TvInputManager.RECORDING_ERROR_UNKNOWN);
             Log.e(TAG, "Tuning was requested from wrong status.");
             return false;
@@ -333,6 +359,10 @@
             mSession.onError(TvInputManager.RECORDING_ERROR_UNKNOWN);
             Log.w(TAG, "Failed to start recording. Couldn't find the channel for " + mChannel);
             return false;
+        } else if (mChannel.isRecordingProhibited()) {
+            mSession.onError(TvInputManager.RECORDING_ERROR_UNKNOWN);
+            Log.w(TAG, "Failed to start recording. Not a recordable channel: " + mChannel);
+            return false;
         }
         if (!mDvrStorageStatusManager.isStorageSufficient()) {
             mSession.onError(TvInputManager.RECORDING_ERROR_INSUFFICIENT_SPACE);
@@ -341,9 +371,9 @@
         }
         mTunerSource = mSourceManager.createDataSource(mContext, mChannel, this);
         if (mTunerSource == null) {
-            mSession.onError(TvInputManager.RECORDING_ERROR_RESOURCE_BUSY);
-            Log.w(TAG, "Tuner stream cannot be created due to resource shortage.");
-            return false;
+            // Retry tuning in this case.
+            mSessionState = STATE_TUNING;
+            return true;
         }
         mSessionState = STATE_TUNED;
         return true;
@@ -365,10 +395,10 @@
         }
         // Since tuning might be happened a while ago, shifts the start position of tuned source.
         mTunerSource.shiftStartPosition(mTunerSource.getBufferedPosition());
-        mBufferManager = new BufferManager(new DvrStorageManager(mStorageDir, true));
         mRecordStartTime = System.currentTimeMillis();
-        mRecorder = new ExoPlayerSampleExtractor(Uri.EMPTY, mTunerSource, mBufferManager, this,
-                true);
+        mDvrStorageManager = new DvrStorageManager(mStorageDir, true);
+        mRecorder = new ExoPlayerSampleExtractor(Uri.EMPTY, mTunerSource,
+                new BufferManager(mDvrStorageManager), this, true);
         mRecorder.setOnCompletionListener(this, mHandler);
         mProgramUri = programUri;
         mSessionState = STATE_RECORDING;
@@ -392,6 +422,34 @@
         Log.i(TAG, "Recording stopped");
     }
 
+    private void updateCaptionTracks(TunerChannel channel, List<PsipData.EitItem> items) {
+        if (mChannel == null || channel == null || mChannel.compareTo(channel) != 0
+                || items == null || items.isEmpty()) {
+            return;
+        }
+        PsipData.EitItem currentProgram = getCurrentProgram(items);
+        if (currentProgram == null || !currentProgram.hasCaptionTrack()
+                || mCurrenProgram != null && mCurrenProgram.compareTo(currentProgram) == 0) {
+            return;
+        }
+        mCurrenProgram = currentProgram;
+        mCaptionTracks = new ArrayList<>(currentProgram.getCaptionTracks());
+        if (DEBUG) {
+            Log.d(TAG, "updated " + mCaptionTracks.size() + " caption tracks for "
+                    + currentProgram);
+        }
+    }
+
+    private PsipData.EitItem getCurrentProgram(List<PsipData.EitItem> items) {
+        for (PsipData.EitItem item : items) {
+            if (mRecordStartTime >= item.getStartTimeUtcMillis()
+                    && mRecordStartTime < item.getEndTimeUtcMillis()) {
+                return item;
+            }
+        }
+        return null;
+    }
+
     private static class Program {
         private final long mChannelId;
         private final String mTitle;
@@ -566,15 +624,25 @@
             return;
         }
         Log.i(TAG, "recording finished " + (success ? "completely" : "partially"));
-        Uri uri = insertRecordedProgram(getRecordedProgram(), mChannel.getChannelId(),
-                Uri.fromFile(mStorageDir).toString(), 1024 * 1024, mRecordStartTime,
-                mRecordStartTime + TimeUnit.MICROSECONDS.toMillis(lastExtractedPositionUs));
+        long recordEndTime =
+                (lastExtractedPositionUs == C.UNKNOWN_TIME_US)
+                        ? System.currentTimeMillis()
+                        : mRecordStartTime + lastExtractedPositionUs / 1000;
+        Uri uri =
+                insertRecordedProgram(
+                        getRecordedProgram(),
+                        mChannel.getChannelId(),
+                        Uri.fromFile(mStorageDir).toString(),
+                        1024 * 1024,
+                        mRecordStartTime,
+                        recordEndTime);
         if (uri == null) {
             new DeleteRecordingTask().execute(mStorageDir);
             mSession.onError(TvInputManager.RECORDING_ERROR_UNKNOWN);
             Log.e(TAG, "Inserting a recording to DB failed");
             return;
         }
+        mDvrStorageManager.writeCaptionInfoFiles(mCaptionTracks);
         mSession.onRecordFinished(uri);
     }
 
diff --git a/src/com/android/tv/tuner/tvinput/TunerSession.java b/src/com/android/tv/tuner/tvinput/TunerSession.java
index 5c61402..44bae90 100644
--- a/src/com/android/tv/tuner/tvinput/TunerSession.java
+++ b/src/com/android/tv/tuner/tvinput/TunerSession.java
@@ -38,12 +38,12 @@
 
 import com.google.android.exoplayer.audio.AudioCapabilities;
 import com.android.tv.tuner.R;
+import com.android.tv.tuner.TunerPreferences;
+import com.android.tv.tuner.TunerPreferences.TunerPreferencesChangedListener;
 import com.android.tv.tuner.cc.CaptionLayout;
 import com.android.tv.tuner.cc.CaptionTrackRenderer;
 import com.android.tv.tuner.data.Cea708Data.CaptionEvent;
 import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
-import com.android.tv.tuner.exoplayer.buffer.BufferManager;
-import com.android.tv.tuner.data.TunerChannel;
 import com.android.tv.tuner.util.GlobalSettingsUtils;
 import com.android.tv.tuner.util.StatusTextUtils;
 import com.android.tv.tuner.util.SystemPropertiesProxy;
@@ -52,7 +52,8 @@
  * Provides a tuner TV input session. It handles Overlay UI works. Main tuner input functions
  * are implemented in {@link TunerSessionWorker}.
  */
-public class TunerSession extends TvInputService.Session implements Handler.Callback {
+public class TunerSession extends TvInputService.Session implements
+        Handler.Callback, TunerPreferencesChangedListener {
     private static final String TAG = "TunerSession";
     private static final boolean DEBUG = false;
     private static final String USBTUNER_SHOW_DEBUG = "persist.tv.tuner.show_debug";
@@ -65,8 +66,9 @@
     public static final int MSG_UI_START_CAPTION_TRACK = 6;
     public static final int MSG_UI_STOP_CAPTION_TRACK = 7;
     public static final int MSG_UI_RESET_CAPTION_TRACK = 8;
-    public static final int MSG_UI_SET_STATUS_TEXT = 9;
-    public static final int MSG_UI_TOAST_RESCAN_NEEDED = 10;
+    public static final int MSG_UI_CLEAR_CAPTION_RENDERER = 9;
+    public static final int MSG_UI_SET_STATUS_TEXT = 10;
+    public static final int MSG_UI_TOAST_RESCAN_NEEDED = 11;
 
     private final Context mContext;
     private final Handler mUiHandler;
@@ -81,8 +83,7 @@
     private boolean mPlayPaused;
     private long mTuneStartTimestamp;
 
-    public TunerSession(Context context, ChannelDataManager channelDataManager,
-            BufferManager bufferManager) {
+    public TunerSession(Context context, ChannelDataManager channelDataManager) {
         super(context);
         mContext = context;
         mUiHandler = new Handler(this);
@@ -97,12 +98,10 @@
         mStatusView.setVisibility(showDebug ? View.VISIBLE : View.INVISIBLE);
         mAudioStatusView = (TextView) mOverlayView.findViewById(R.id.audio_status);
         mAudioStatusView.setVisibility(View.INVISIBLE);
-        mAudioStatusView.setText(Html.fromHtml(StatusTextUtils.getAudioWarningInHTML(
-                context.getString(R.string.ut_surround_sound_disabled))));
         CaptionLayout captionLayout = (CaptionLayout) mOverlayView.findViewById(R.id.caption);
         mCaptionTrackRenderer = new CaptionTrackRenderer(captionLayout);
-        mSessionWorker = new TunerSessionWorker(context, channelDataManager,
-                bufferManager, this);
+        mSessionWorker = new TunerSessionWorker(context, channelDataManager, this);
+        TunerPreferences.setTunerPreferencesChangedListener(this);
     }
 
     public boolean isReleased() {
@@ -214,6 +213,7 @@
         mReleased = true;
         mSessionWorker.release();
         mUiHandler.removeCallbacksAndMessages(null);
+        TunerPreferences.setTunerPreferencesChangedListener(null);
     }
 
     /**
@@ -272,10 +272,13 @@
                 // setting is "never".
                 final int value = GlobalSettingsUtils.getEncodedSurroundOutputSettings(mContext);
                 if (value == GlobalSettingsUtils.ENCODED_SURROUND_OUTPUT_NEVER) {
-                    mAudioStatusView.setVisibility(View.VISIBLE);
+                    mAudioStatusView.setText(Html.fromHtml(StatusTextUtils.getAudioWarningInHTML(
+                            mContext.getString(R.string.ut_surround_sound_disabled))));
                 } else {
-                    Log.e(TAG, "Audio is unavailable, surround sound setting is " + value);
+                    mAudioStatusView.setText(Html.fromHtml(StatusTextUtils.getAudioWarningInHTML(
+                            mContext.getString(R.string.audio_passthrough_not_supported))));
                 }
+                mAudioStatusView.setVisibility(View.VISIBLE);
                 return true;
             }
             case MSG_UI_HIDE_AUDIO_UNPLAYABLE: {
@@ -298,6 +301,10 @@
                 mCaptionTrackRenderer.reset();
                 return true;
             }
+            case MSG_UI_CLEAR_CAPTION_RENDERER: {
+                mCaptionTrackRenderer.clear();
+                return true;
+            }
             case MSG_UI_SET_STATUS_TEXT: {
                 mStatusView.setText((CharSequence) msg.obj);
                 return true;
@@ -309,4 +316,9 @@
         }
         return false;
     }
+
+    @Override
+    public void onTunerPreferencesChanged() {
+        mSessionWorker.sendMessage(TunerSessionWorker.MSG_TUNER_PREFERENCES_CHANGED);
+    }
 }
diff --git a/src/com/android/tv/tuner/tvinput/TunerSessionWorker.java b/src/com/android/tv/tuner/tvinput/TunerSessionWorker.java
index 5230298..e7eb017 100644
--- a/src/com/android/tv/tuner/tvinput/TunerSessionWorker.java
+++ b/src/com/android/tv/tuner/tvinput/TunerSessionWorker.java
@@ -27,6 +27,7 @@
 import android.media.tv.TvInputManager;
 import android.media.tv.TvTrackInfo;
 import android.net.Uri;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
@@ -35,6 +36,7 @@
 import android.support.annotation.MainThread;
 import android.support.annotation.WorkerThread;
 import android.text.Html;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
@@ -45,7 +47,10 @@
 import com.google.android.exoplayer.ExoPlayer;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.TvContentRatingCache;
+import com.android.tv.customization.TvCustomizationManager;
+import com.android.tv.customization.TvCustomizationManager.TRICKPLAY_MODE;
 import com.android.tv.tuner.TunerPreferences;
+import com.android.tv.tuner.TunerPreferences.TrickplaySetting;
 import com.android.tv.tuner.data.Cea708Data;
 import com.android.tv.tuner.data.PsipData.EitItem;
 import com.android.tv.tuner.data.PsipData.TvTracksInterface;
@@ -55,20 +60,23 @@
 import com.android.tv.tuner.data.nano.Track.AtscCaptionTrack;
 import com.android.tv.tuner.exoplayer.MpegTsRendererBuilder;
 import com.android.tv.tuner.exoplayer.buffer.BufferManager;
+import com.android.tv.tuner.exoplayer.buffer.BufferManager.StorageManager;
 import com.android.tv.tuner.exoplayer.buffer.DvrStorageManager;
 import com.android.tv.tuner.exoplayer.MpegTsPlayer;
+import com.android.tv.tuner.exoplayer.buffer.TrickplayStorageManager;
+import com.android.tv.tuner.exoplayer.ffmpeg.FfmpegDecoderClient;
 import com.android.tv.tuner.source.TsDataSource;
 import com.android.tv.tuner.source.TsDataSourceManager;
 import com.android.tv.tuner.util.StatusTextUtils;
+import com.android.tv.tuner.util.SystemPropertiesProxy;
 
 import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
 
 /**
  * {@link TunerSessionWorker} implements a handler thread which processes TV input jobs
@@ -82,6 +90,9 @@
     private static final boolean DEBUG = false;
     private static final boolean ENABLE_PROFILER = true;
     private static final String PLAY_FROM_CHANNEL = "channel";
+    private static final String MAX_BUFFER_SIZE_KEY = "tv.tuner.buffersize_mbytes";
+    private static final int MAX_BUFFER_SIZE_DEF = 2 * 1024;  // 2GB
+    private static final int MIN_BUFFER_SIZE_DEF = 256;  // 256MB
 
     // Public messages
     public static final int MSG_SELECT_TRACK = 1;
@@ -93,6 +104,7 @@
     public static final int MSG_TIMESHIFT_SET_PLAYBACKPARAMS = 7;
     public static final int MSG_AUDIO_CAPABILITIES_CHANGED = 8;
     public static final int MSG_UNBLOCKED_RATING = 9;
+    public static final int MSG_TUNER_PREFERENCES_CHANGED = 10;
 
     // Private messages
     private static final int MSG_TUNE = 1000;
@@ -147,10 +159,20 @@
     private static final int EXPECTED_KEY_FRAME_INTERVAL_MS = 500;
     private static final int MIN_TRICKPLAY_SEEK_INTERVAL_MS = 20;
     private static final int TRICKPLAY_MONITOR_INTERVAL_MS = 250;
+    private static final int RELEASE_WAIT_INTERVAL_MS = 50;
+    private static final long TRICKPLAY_OFF_DURATION_MS = TimeUnit.DAYS.toMillis(14);
+
+    // Since release() is done asynchronously, synchronization between multiple TunerSessionWorker
+    // creation/release is required.
+    // This is used to guarantee that at most one active TunerSessionWorker exists at any give time.
+    private static Semaphore sActiveSessionSemaphore = new Semaphore(1);
 
     private final Context mContext;
     private final ChannelDataManager mChannelDataManager;
     private final TsDataSourceManager mSourceManager;
+    private final int mMaxTrickplayBufferSizeMb;
+    private final File mTrickplayBufferDir;
+    private final @TRICKPLAY_MODE int mTrickplayModeCustomization;
     private volatile Surface mSurface;
     private volatile float mVolume = 1.0f;
     private volatile boolean mCaptionEnabled;
@@ -159,6 +181,9 @@
     private volatile Long mRecordingDuration;
     private volatile long mRecordStartTimeMs;
     private volatile long mBufferStartTimeMs;
+    private volatile boolean mTrickplayDisabledByStorageIssue;
+    private @TrickplaySetting int mTrickplaySetting;
+    private long mTrickplayExpiredMs;
     private String mRecordingId;
     private final Handler mHandler;
     private int mRetryCount;
@@ -177,19 +202,20 @@
     private TvContentRating mUnblockedContentRating;
     private long mLastPositionMs;
     private AudioCapabilities mAudioCapabilities;
-    private final CountDownLatch mReleaseLatch = new CountDownLatch(1);
     private long mLastLimitInBytes;
-    private long mLastPositionInBytes;
-    private final BufferManager mBufferManager;
     private final TvContentRatingCache mTvContentRatingCache = TvContentRatingCache.getInstance();
     private final TunerSession mSession;
+    private final boolean mHasSoftwareAudioDecoder;
     private int mPlayerState = ExoPlayer.STATE_IDLE;
     private long mPreparingStartTimeMs;
     private long mBufferingStartTimeMs;
     private long mReadyStartTimeMs;
+    private boolean mIsActiveSession;
+    private boolean mReleaseRequested; // Guarded by mReleaseLock
+    private final Object mReleaseLock = new Object();
 
     public TunerSessionWorker(Context context, ChannelDataManager channelDataManager,
-                BufferManager bufferManager, TunerSession tunerSession) {
+                TunerSession tunerSession) {
         if (DEBUG) Log.d(TAG, "TunerSessionWorker created");
         mContext = context;
 
@@ -211,10 +237,39 @@
                 (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);
         mCaptionEnabled = captioningManager.isEnabled();
         mPlaybackParams.setSpeed(1.0f);
-        mBufferManager = bufferManager;
+        mMaxTrickplayBufferSizeMb =
+                SystemPropertiesProxy.getInt(MAX_BUFFER_SIZE_KEY, MAX_BUFFER_SIZE_DEF);
+        mTrickplayModeCustomization = TvCustomizationManager.getTrickplayMode(context);
+        if (mTrickplayModeCustomization ==
+                TvCustomizationManager.TRICKPLAY_MODE_USE_EXTERNAL_STORAGE) {
+            boolean useExternalStorage =
+                    Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()) &&
+                    Environment.isExternalStorageRemovable();
+            mTrickplayBufferDir = useExternalStorage ? context.getExternalCacheDir() : null;
+        } else if (mTrickplayModeCustomization == TvCustomizationManager.TRICKPLAY_MODE_ENABLED) {
+            mTrickplayBufferDir = context.getCacheDir();
+        } else {
+            mTrickplayBufferDir = null;
+        }
+        mTrickplayDisabledByStorageIssue = mTrickplayBufferDir == null;
+        mTrickplaySetting = TunerPreferences.getTrickplaySetting(context);
+        if (mTrickplaySetting != TunerPreferences.TRICKPLAY_SETTING_NOT_SET
+                && mTrickplayModeCustomization
+                        == TvCustomizationManager.TRICKPLAY_MODE_USE_EXTERNAL_STORAGE) {
+            // Consider the case of Customization package updates the value of trickplay mode
+            // to TRICKPLAY_MODE_USE_EXTERNAL_STORAGE after install.
+            mTrickplaySetting = TunerPreferences.TRICKPLAY_SETTING_NOT_SET;
+            TunerPreferences.setTrickplaySetting(context, mTrickplaySetting);
+            TunerPreferences.setTrickplayExpiredMs(context, 0);
+        }
+        mTrickplayExpiredMs = TunerPreferences.getTrickplayExpiredMs(context);
         mPreparingStartTimeMs = INVALID_TIME;
         mBufferingStartTimeMs = INVALID_TIME;
         mReadyStartTimeMs = INVALID_TIME;
+        // NOTE: We assume that TunerSessionWorker instance will be at most one.
+        // Only one TunerSessionWorker can be connected to FfmpegDecoderClient at any given time.
+        // connect() will return false, if there is a connected TunerSessionWorker already.
+        mHasSoftwareAudioDecoder = FfmpegDecoderClient.connect(context);
     }
 
     // Public methods
@@ -285,24 +340,21 @@
     }
 
     private Long getDurationForRecording(String recordingId) {
-        try {
-            DvrStorageManager storageManager =
+        DvrStorageManager storageManager =
                     new DvrStorageManager(new File(getRecordingPath()), false);
-            Pair<String, MediaFormat> trackInfo = null;
-            try {
-                trackInfo = storageManager.readTrackInfoFile(false);
-            } catch (FileNotFoundException e) {
-            }
-            if (trackInfo == null) {
-                trackInfo = storageManager.readTrackInfoFile(true);
-            }
-            Long durationUs = trackInfo.second.getLong(MediaFormat.KEY_DURATION);
+        List<BufferManager.TrackFormat> trackFormatList =
+                    storageManager.readTrackInfoFiles(false);
+        if (trackFormatList.isEmpty()) {
+                trackFormatList = storageManager.readTrackInfoFiles(true);
+        }
+        if (!trackFormatList.isEmpty()) {
+            BufferManager.TrackFormat trackFormat = trackFormatList.get(0);
+            Long durationUs = trackFormat.format.getLong(MediaFormat.KEY_DURATION);
             // we need duration by milli for trickplay notification.
             return durationUs != null ? durationUs / 1000 : null;
-        } catch (IOException e) {
-            Log.e(TAG, "meta file for recording was not found: " + recordingId);
-            return null;
         }
+        Log.e(TAG, "meta file for recording was not found: " + recordingId);
+        return null;
     }
 
     @MainThread
@@ -341,16 +393,15 @@
     @MainThread
     public void release() {
         if (DEBUG) Log.d(TAG, "release()");
+        synchronized (mReleaseLock) {
+            mReleaseRequested = true;
+        }
+        if (mHasSoftwareAudioDecoder) {
+            FfmpegDecoderClient.disconnect(mContext);
+        }
         mChannelDataManager.setListener(null);
         mHandler.removeCallbacksAndMessages(null);
         mHandler.sendEmptyMessage(MSG_RELEASE);
-        try {
-            mReleaseLatch.await();
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Couldn't wait for finish of MSG_RELEASE", e);
-        } finally {
-            mHandler.getLooper().quitSafely();
-        }
     }
 
     // MpegTsPlayer.Listener
@@ -367,7 +418,7 @@
         if (playbackState == ExoPlayer.STATE_READY) {
             if (DEBUG) Log.d(TAG, "ExoPlayer ready");
             if (!mPlayerStarted) {
-                sendMessage(MSG_START_PLAYBACK, mPlayer);
+                sendMessage(MSG_START_PLAYBACK, System.identityHashCode(mPlayer));
             }
             mReadyStartTimeMs = SystemClock.elapsedRealtime();
         } else if (playbackState == ExoPlayer.STATE_PREPARING) {
@@ -379,7 +430,7 @@
             // notification of STATE_ENDED from MpegTsPlayer will be ignored afterwards.
             Log.i(TAG, "Player ended: end of stream");
             if (mChannel != null) {
-                sendMessage(MSG_RETRY_PLAYBACK, mPlayer);
+                sendMessage(MSG_RETRY_PLAYBACK, System.identityHashCode(mPlayer));
             }
         }
         mPlayerState = playbackState;
@@ -397,7 +448,8 @@
         // If we are playing live stream, retrying playback maybe helpful. But for recorded stream,
         // retrying playback is not helpful.
         if (mChannel != null) {
-            mHandler.obtainMessage(MSG_RETRY_PLAYBACK, mPlayer).sendToTarget();
+            mHandler.obtainMessage(MSG_RETRY_PLAYBACK, System.identityHashCode(mPlayer))
+                    .sendToTarget();
         }
     }
 
@@ -415,8 +467,12 @@
     public void onDrawnToSurface(MpegTsPlayer player, Surface surface) {
         if (mSurface != null && mPlayerStarted) {
             if (DEBUG) Log.d(TAG, "MSG_DRAWN_TO_SURFACE");
-            mBufferStartTimeMs = mRecordStartTimeMs =
-                    (mRecordingId != null) ? 0 : System.currentTimeMillis();
+            if (mRecordingId != null) {
+                // Workaround of b/33298048: set it to 1 instead of 0.
+                mBufferStartTimeMs = mRecordStartTimeMs = 1;
+            } else {
+                mBufferStartTimeMs = mRecordStartTimeMs = System.currentTimeMillis();
+            }
             notifyVideoAvailable();
             mReportedDrawnToSurface = true;
 
@@ -461,6 +517,11 @@
     }
 
     @Override
+    public void onClearCaptionEvent() {
+        mSession.sendUiMessage(TunerSession.MSG_UI_CLEAR_CAPTION_RENDERER);
+    }
+
+    @Override
     public void onDiscoverCaptionServiceNumber(int serviceNumber) {
         sendMessage(MSG_DISCOVER_CAPTION_SERVICE_NUMBER, serviceNumber);
     }
@@ -499,7 +560,8 @@
 
     @Override
     public void onDiskTooSlow() {
-        sendMessage(MSG_RETRY_PLAYBACK, mPlayer);
+        mTrickplayDisabledByStorageIssue = true;
+        sendMessage(MSG_RETRY_PLAYBACK, System.identityHashCode(mPlayer));
     }
 
     // EventDetector.EventListener
@@ -602,6 +664,28 @@
                     return true;
                 }
                 notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
+                if (!mIsActiveSession) {
+                    // Wait until release is finished if there is a pending release.
+                    try {
+                        while (!sActiveSessionSemaphore.tryAcquire(
+                                RELEASE_WAIT_INTERVAL_MS, TimeUnit.MILLISECONDS)) {
+                            synchronized (mReleaseLock) {
+                                if (mReleaseRequested) {
+                                    return true;
+                                }
+                            }
+                        }
+                    } catch (InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                    }
+                    synchronized (mReleaseLock) {
+                        if (mReleaseRequested) {
+                            sActiveSessionSemaphore.release();
+                            return true;
+                        }
+                    }
+                    mIsActiveSession = true;
+                }
                 Uri channelUri = (Uri) msg.obj;
                 String recording = null;
                 long channelId = parseChannel(channelUri);
@@ -616,7 +700,8 @@
                     notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN);
                     return true;
                 }
-                mHandler.removeCallbacksAndMessages(null);
+                clearCallbacksAndMessagesSafely();
+                mChannelDataManager.removeAllCallbacksAndMessages();
                 if (channel != null) {
                     mChannelDataManager.requestProgramsData(channel);
                 }
@@ -624,8 +709,8 @@
                 // TODO: Need to refactor. notifyContentAllowed() should not be called if parental
                 // control is turned on.
                 mSession.notifyContentAllowed();
-                resetPlayback();
                 resetTvTracks();
+                resetPlayback();
                 mHandler.sendEmptyMessageDelayed(MSG_RESCHEDULE_PROGRAMS,
                         RESCHEDULE_PROGRAMS_INITIAL_DELAY_MS);
                 return true;
@@ -633,7 +718,7 @@
             case MSG_STOP_TUNE: {
                 if (DEBUG) Log.d(TAG, "MSG_STOP_TUNE");
                 mChannel = null;
-                stopPlayback();
+                stopPlayback(true);
                 stopCaptionTrack();
                 resetTvTracks();
                 notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN);
@@ -642,14 +727,17 @@
             case MSG_RELEASE: {
                 if (DEBUG) Log.d(TAG, "MSG_RELEASE");
                 mHandler.removeCallbacksAndMessages(null);
-                stopPlayback();
+                stopPlayback(true);
                 stopCaptionTrack();
                 mSourceManager.release();
-                mReleaseLatch.countDown();
+                mHandler.getLooper().quitSafely();
+                if (mIsActiveSession) {
+                    sActiveSessionSemaphore.release();
+                }
                 return true;
             }
             case MSG_RETRY_PLAYBACK: {
-                if (mPlayer == msg.obj) {
+                if (System.identityHashCode(mPlayer) == (int) msg.obj) {
                     Log.i(TAG, "Retrying the playback for channel: " + mChannel);
                     mHandler.removeMessages(MSG_RETRY_PLAYBACK);
                     // When there is a request of retrying playback, don't reuse TunerHal.
@@ -658,16 +746,18 @@
                     if (DEBUG) {
                         Log.d(TAG, "MSG_RETRY_PLAYBACK " + mRetryCount);
                     }
+                    mChannelDataManager.removeAllCallbacksAndMessages();
                     if (mRetryCount <= MAX_IMMEDIATE_RETRY_COUNT) {
                         resetPlayback();
                     } else {
                         // When it reaches this point, it may be due to an error that occurred in
                         // the tuner device. Calling stopPlayback() resets the tuner device
                         // to recover from the error.
-                        stopPlayback();
+                        stopPlayback(false);
                         stopCaptionTrack();
 
                         notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL);
+                        Log.i(TAG, "Notify weak signal since fail to retry playback");
 
                         // After MAX_IMMEDIATE_RETRY_COUNT, give some delay of an empirically chosen
                         // value before recovering the playback.
@@ -679,13 +769,14 @@
             }
             case MSG_RESET_PLAYBACK: {
                 if (DEBUG) Log.d(TAG, "MSG_RESET_PLAYBACK");
+                mChannelDataManager.removeAllCallbacksAndMessages();
                 resetPlayback();
                 return true;
             }
             case MSG_START_PLAYBACK: {
                 if (DEBUG) Log.d(TAG, "MSG_START_PLAYBACK");
                 if (mChannel != null || mRecordingId != null) {
-                    startPlayback(msg.obj);
+                    startPlayback((int) msg.obj);
                 }
                 return true;
             }
@@ -790,7 +881,11 @@
                 return true;
             }
             case MSG_RESCHEDULE_PROGRAMS: {
-                doReschedulePrograms();
+                if (mHandler.hasMessages(MSG_SCHEDULE_OF_PROGRAMS)) {
+                    mHandler.sendEmptyMessage(MSG_RESCHEDULE_PROGRAMS);
+                } else {
+                    doReschedulePrograms();
+                }
                 return true;
             }
             case MSG_PARENTAL_CONTROLS: {
@@ -814,11 +909,8 @@
                 return true;
             }
             case MSG_SELECT_TRACK: {
-                if (mChannel != null) {
+                if (mChannel != null || mRecordingId != null) {
                     doSelectTrack(msg.arg1, (String) msg.obj);
-                } else if (mRecordingId != null) {
-                    // TODO : mChannel == null && mRecordingId != null
-                    Log.d(TAG, "track selected for recording");
                 }
                 return true;
             }
@@ -835,6 +927,7 @@
                 if (mPlayer == null) {
                     return true;
                 }
+                setTrickplayEnabledIfNeeded();
                 doTimeShiftPause();
                 return true;
             }
@@ -843,6 +936,7 @@
                 if (mPlayer == null) {
                     return true;
                 }
+                setTrickplayEnabledIfNeeded();
                 doTimeShiftResume();
                 return true;
             }
@@ -852,6 +946,7 @@
                 if (mPlayer == null) {
                     return true;
                 }
+                setTrickplayEnabledIfNeeded();
                 doTimeShiftSeekTo(position);
                 return true;
             }
@@ -859,6 +954,7 @@
                 if (mPlayer == null) {
                     return true;
                 }
+                setTrickplayEnabledIfNeeded();
                 doTimeShiftSetPlaybackParams((PlaybackParams) msg.obj);
                 return true;
             }
@@ -883,6 +979,22 @@
                 }
                 return true;
             }
+            case MSG_TUNER_PREFERENCES_CHANGED: {
+                mHandler.removeMessages(MSG_TUNER_PREFERENCES_CHANGED);
+                @TrickplaySetting int trickplaySetting =
+                        TunerPreferences.getTrickplaySetting(mContext);
+                if (trickplaySetting != mTrickplaySetting) {
+                    boolean wasTrcikplayEnabled =
+                        mTrickplaySetting != TunerPreferences.TRICKPLAY_SETTING_DISABLED;
+                    boolean isTrickplayEnabled =
+                        trickplaySetting != TunerPreferences.TRICKPLAY_SETTING_DISABLED;
+                    mTrickplaySetting = trickplaySetting;
+                    if (isTrickplayEnabled != wasTrcikplayEnabled) {
+                        sendMessage(MSG_RESET_PLAYBACK, System.identityHashCode(mPlayer));
+                    }
+                }
+                return true;
+            }
             case MSG_BUFFER_START_TIME_CHANGED: {
                 if (mPlayer == null) {
                     return true;
@@ -891,7 +1003,7 @@
                 if (!hasEnoughBackwardBuffer()
                         && (!mPlayer.isPlaying() || mPlaybackParams.getSpeed() < 1.0f)) {
                     mPlayer.setPlayWhenReady(true);
-                    mPlayer.setAudioTrack(true);
+                    mPlayer.setAudioTrackAndClosedCaption(true);
                     mPlaybackParams.setSpeed(1.0f);
                 }
                 return true;
@@ -909,7 +1021,6 @@
                 }
                 TsDataSource source = mPlayer.getDataSource();
                 long limitInBytes = source != null ? source.getBufferedPosition() : 0L;
-                long positionInBytes = source != null ? source.getLastReadPosition() : 0L;
                 if (TunerDebug.ENABLED) {
                     TunerDebug.calculateDiff();
                     mSession.sendUiMessage(TunerSession.MSG_UI_SET_STATUS_TEXT,
@@ -927,32 +1038,36 @@
                                             TunerDebug.getVideoPtsUsRate()
                                     )));
                 }
-                if (DEBUG) {
-                    Log.d(TAG, String.format("MSG_CHECK_SIGNAL position: %d, limit: %d",
-                            positionInBytes, limitInBytes));
-                }
                 mSession.sendUiMessage(TunerSession.MSG_UI_HIDE_MESSAGE);
                 long currentTime = SystemClock.elapsedRealtime();
-                boolean noBufferRead = positionInBytes == mLastPositionInBytes
-                        && limitInBytes == mLastLimitInBytes;
-                boolean isBufferingTooLong = mBufferingStartTimeMs != INVALID_TIME
-                        && currentTime - mBufferingStartTimeMs
-                                > PLAYBACK_STATE_CHANGED_WAITING_THRESHOLD_MS;
-                boolean isPreparingTooLong = mPreparingStartTimeMs != INVALID_TIME
-                        && currentTime - mPreparingStartTimeMs
-                        > PLAYBACK_STATE_CHANGED_WAITING_THRESHOLD_MS;
+                long bufferingTimeMs = mBufferingStartTimeMs != INVALID_TIME
+                        ? currentTime - mBufferingStartTimeMs : mBufferingStartTimeMs;
+                long preparingTimeMs = mPreparingStartTimeMs != INVALID_TIME
+                        ? currentTime - mPreparingStartTimeMs : mPreparingStartTimeMs;
+                boolean isBufferingTooLong =
+                        bufferingTimeMs > PLAYBACK_STATE_CHANGED_WAITING_THRESHOLD_MS;
+                boolean isPreparingTooLong =
+                        preparingTimeMs > PLAYBACK_STATE_CHANGED_WAITING_THRESHOLD_MS;
                 boolean isWeakSignal = source != null
-                        && mChannel.getType() == Channel.TYPE_TUNER
-                        && (noBufferRead || isBufferingTooLong || isPreparingTooLong);
+                        && mChannel.getType() != Channel.TYPE_FILE
+                        && (isBufferingTooLong || isPreparingTooLong);
                 if (isWeakSignal && !mReportedWeakSignal) {
                     if (!mHandler.hasMessages(MSG_RETRY_PLAYBACK)) {
-                        mHandler.sendMessageDelayed(mHandler.obtainMessage(
-                                MSG_RETRY_PLAYBACK, mPlayer), PLAYBACK_RETRY_DELAY_MS);
+                        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RETRY_PLAYBACK,
+                                System.identityHashCode(mPlayer)), PLAYBACK_RETRY_DELAY_MS);
                     }
                     if (mPlayer != null) {
-                        mPlayer.setAudioTrack(false);
+                        mPlayer.setAudioTrackAndClosedCaption(false);
                     }
                     notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL);
+                    Log.i(TAG, "Notify weak signal due to signal check, " + String.format(
+                            "packetsPerSec:%d, bufferingTimeMs:%d, preparingTimeMs:%d, " +
+                                    "videoFrameDrop:%d",
+                            (limitInBytes - mLastLimitInBytes) / TS_PACKET_SIZE,
+                            bufferingTimeMs,
+                            preparingTimeMs,
+                            TunerDebug.getVideoFrameDrop()
+                    ));
                 } else if (!isWeakSignal && mReportedWeakSignal) {
                     boolean isPlaybackStable = mReadyStartTimeMs != INVALID_TIME
                             && currentTime - mReadyStartTimeMs
@@ -962,11 +1077,10 @@
                     } else if (mReportedDrawnToSurface) {
                         mHandler.removeMessages(MSG_RETRY_PLAYBACK);
                         notifyVideoAvailable();
-                        mPlayer.setAudioTrack(true);
+                        mPlayer.setAudioTrackAndClosedCaption(true);
                     }
                 }
                 mLastLimitInBytes = limitInBytes;
-                mLastPositionInBytes = positionInBytes;
                 mHandler.sendEmptyMessageDelayed(MSG_CHECK_SIGNAL, CHECK_NO_SIGNAL_PERIOD_MS);
                 return true;
             }
@@ -999,15 +1113,8 @@
             if (trackId == null) {
                 return;
             }
-            AtscAudioTrack audioTrack = mAudioTrackMap.get(numTrackId);
-            if (audioTrack == null) {
-                return;
-            }
-            int oldAudioPid = mChannel.getAudioPid();
-            mChannel.selectAudioTrack(audioTrack.index);
-            int newAudioPid = mChannel.getAudioPid();
-            if (oldAudioPid != newAudioPid) {
-                mPlayer.setSelectedTrack(MpegTsPlayer.TRACK_TYPE_AUDIO, audioTrack.index);
+            if (numTrackId != mPlayer.getSelectedTrack(MpegTsPlayer.TRACK_TYPE_AUDIO)) {
+                mPlayer.setSelectedTrack(MpegTsPlayer.TRACK_TYPE_AUDIO, numTrackId);
             }
             mSession.notifyTrackSelected(type, trackId);
         } else if (type == TvTrackInfo.TYPE_SUBTITLE) {
@@ -1030,11 +1137,49 @@
         }
     }
 
-    private MpegTsPlayer createPlayer(AudioCapabilities capabilities, BufferManager bufferManager) {
+    private void setTrickplayEnabledIfNeeded() {
+        if (mChannel == null ||
+                mTrickplayModeCustomization != TvCustomizationManager.TRICKPLAY_MODE_ENABLED) {
+            return;
+        }
+        if (mTrickplaySetting == TunerPreferences.TRICKPLAY_SETTING_NOT_SET) {
+            mTrickplaySetting = TunerPreferences.TRICKPLAY_SETTING_ENABLED;
+            TunerPreferences.setTrickplaySetting(
+                    mContext, mTrickplaySetting);
+        }
+    }
+
+    private MpegTsPlayer createPlayer(AudioCapabilities capabilities) {
         if (capabilities == null) {
             Log.w(TAG, "No Audio Capabilities");
         }
-
+        long now = System.currentTimeMillis();
+        if (mTrickplayModeCustomization == TvCustomizationManager.TRICKPLAY_MODE_ENABLED
+                && mTrickplaySetting == TunerPreferences.TRICKPLAY_SETTING_NOT_SET) {
+            if (mTrickplayExpiredMs == 0) {
+                mTrickplayExpiredMs = now + TRICKPLAY_OFF_DURATION_MS;
+                TunerPreferences.setTrickplayExpiredMs(mContext, mTrickplayExpiredMs);
+            } else {
+                if (mTrickplayExpiredMs < now) {
+                    mTrickplaySetting = TunerPreferences.TRICKPLAY_SETTING_DISABLED;
+                    TunerPreferences.setTrickplaySetting(mContext, mTrickplaySetting);
+                }
+            }
+        }
+        BufferManager bufferManager = null;
+        if (mRecordingId != null) {
+            StorageManager storageManager =
+                    new DvrStorageManager(new File(getRecordingPath()), false);
+            bufferManager = new BufferManager(storageManager);
+            updateCaptionTracks(((DvrStorageManager)storageManager).readCaptionInfoFiles());
+        } else if (!mTrickplayDisabledByStorageIssue
+                && mTrickplaySetting != TunerPreferences.TRICKPLAY_SETTING_DISABLED
+                && mMaxTrickplayBufferSizeMb >= MIN_BUFFER_SIZE_DEF) {
+            bufferManager = new BufferManager(new TrickplayStorageManager(mContext,
+                    mTrickplayBufferDir, 1024L * 1024 * mMaxTrickplayBufferSizeMb));
+        } else {
+            Log.w(TAG, "Trickplay is disabled.");
+        }
         MpegTsPlayer player = new MpegTsPlayer(
                 new MpegTsRendererBuilder(mContext, bufferManager, this),
                 mHandler, mSourceManager, capabilities, this);
@@ -1069,24 +1214,26 @@
     }
 
     private void updateTvTracks(TvTracksInterface tvTracksInterface, boolean fromPmt) {
-        if (DEBUG) {
-            Log.d(TAG, "UpdateTvTracks " + tvTracksInterface);
-        }
-        List<AtscAudioTrack> audioTracks = tvTracksInterface.getAudioTracks();
-        List<AtscCaptionTrack> captionTracks = tvTracksInterface.getCaptionTracks();
-        // According to ATSC A/69 chapter 6.9, both PMT and EIT should have descriptors for audio
-        // tracks, but in real world, we see some bogus audio track info in EIT, so, we trust audio
-        // track info in PMT more and use info in EIT only when we have nothing.
-        if (audioTracks != null && !audioTracks.isEmpty()
-                && (mChannel.getAudioTracks() == null || fromPmt)) {
-            updateAudioTracks(audioTracks);
-        }
-        if (captionTracks == null || captionTracks.isEmpty()) {
-            if (tvTracksInterface.hasCaptionTrack()) {
+        synchronized (tvTracksInterface) {
+            if (DEBUG) {
+                Log.d(TAG, "UpdateTvTracks " + tvTracksInterface);
+            }
+            List<AtscAudioTrack> audioTracks = tvTracksInterface.getAudioTracks();
+            List<AtscCaptionTrack> captionTracks = tvTracksInterface.getCaptionTracks();
+            // According to ATSC A/69 chapter 6.9, both PMT and EIT should have descriptors for audio
+            // tracks, but in real world, we see some bogus audio track info in EIT, so, we trust audio
+            // track info in PMT more and use info in EIT only when we have nothing.
+            if (audioTracks != null && !audioTracks.isEmpty()
+                    && (mChannel == null || mChannel.getAudioTracks() == null || fromPmt)) {
+                updateAudioTracks(audioTracks);
+            }
+            if (captionTracks == null || captionTracks.isEmpty()) {
+                if (tvTracksInterface.hasCaptionTrack()) {
+                    updateCaptionTracks(captionTracks);
+                }
+            } else {
                 updateCaptionTracks(captionTracks);
             }
-        } else {
-            updateCaptionTracks(captionTracks);
         }
     }
 
@@ -1132,25 +1279,24 @@
         int audioTrackCount = mPlayer.getTrackCount(MpegTsPlayer.TRACK_TYPE_AUDIO);
         removeTvTracks(TvTrackInfo.TYPE_AUDIO);
         for (int i = 0; i < audioTrackCount; i++) {
-            AtscAudioTrack audioTrack = mAudioTrackMap.get(i);
-            if (audioTrack == null) {
-                continue;
-            }
-            String language = audioTrack.language;
-            if (language == null && mChannel.getAudioTracks() != null
-                    && mChannel.getAudioTracks().size() == mAudioTrackMap.size()) {
-                // If a language is not present, use a language field in PMT section parsed.
-                language = mChannel.getAudioTracks().get(i).language;
-            }
-            // Save the index to the audio track.
-            // Later, when an audio track is selected, both the audio pid and its audio stream
-            // type reside in the selected index position of the tuner channel's audio data.
-            audioTrack.index = i;
+            // We use language information from EIT/VCT only when the player does not provide
+            // languages.
+            com.google.android.exoplayer.MediaFormat infoFromPlayer =
+                    mPlayer.getTrackFormat(MpegTsPlayer.TRACK_TYPE_AUDIO, i);
+            AtscAudioTrack infoFromEit = mAudioTrackMap.get(i);
+            AtscAudioTrack infoFromVct = (mChannel != null
+                    && mChannel.getAudioTracks().size() == mAudioTrackMap.size()
+                    && i < mChannel.getAudioTracks().size())
+                    ? mChannel.getAudioTracks().get(i) : null;
+            String language = !TextUtils.isEmpty(infoFromPlayer.language) ? infoFromPlayer.language
+                    : (infoFromEit != null && infoFromEit.language != null) ? infoFromEit.language
+                            : (infoFromVct != null && infoFromVct.language != null)
+                                    ? infoFromVct.language : null;
             TvTrackInfo.Builder builder = new TvTrackInfo.Builder(
                     TvTrackInfo.TYPE_AUDIO, AUDIO_TRACK_PREFIX + i);
             builder.setLanguage(language);
-            builder.setAudioChannelCount(audioTrack.channelCount);
-            builder.setAudioSampleRate(audioTrack.sampleRate);
+            builder.setAudioChannelCount(infoFromPlayer.channelCount);
+            builder.setAudioSampleRate(infoFromPlayer.sampleRate);
             TvTrackInfo track = builder.build();
             mTvTracks.add(track);
         }
@@ -1226,8 +1372,10 @@
         }
     }
 
-    private void stopPlayback() {
-        mChannelDataManager.removeAllCallbacksAndMessages();
+    private void stopPlayback(boolean removeChannelDataCallbacks) {
+        if (removeChannelDataCallbacks) {
+            mChannelDataManager.removeAllCallbacksAndMessages();
+        }
         if (mPlayer != null) {
             mPlayer.setPlayWhenReady(false);
             mPlayer.release();
@@ -1239,14 +1387,15 @@
             mPreparingStartTimeMs = INVALID_TIME;
             mBufferingStartTimeMs = INVALID_TIME;
             mReadyStartTimeMs = INVALID_TIME;
+            mLastLimitInBytes = 0L;
             mSession.sendUiMessage(TunerSession.MSG_UI_HIDE_AUDIO_UNPLAYABLE);
             mSession.notifyTimeShiftStatusChanged(TvInputManager.TIME_SHIFT_STATUS_UNAVAILABLE);
         }
     }
 
-    private void startPlayback(Object playerObj) {
+    private void startPlayback(int playerHashCode) {
         // TODO: provide hasAudio()/hasVideo() for play recordings.
-        if (mPlayer == null || mPlayer != playerObj) {
+        if (mPlayer == null || System.identityHashCode(mPlayer) != playerHashCode) {
             return;
         }
         if (mChannel != null && !mChannel.hasAudio()) {
@@ -1257,9 +1406,12 @@
             return;
         }
         if (mChannel != null && ((mChannel.hasAudio() && !mPlayer.hasAudio())
-                || (mChannel.hasVideo() && !mPlayer.hasVideo()))) {
-            // Tracks haven't been detected in the extractor. Try again.
-            sendMessage(MSG_RETRY_PLAYBACK, mPlayer);
+                || (mChannel.hasVideo() && !mPlayer.hasVideo()))
+                && mChannel.getType() != Channel.TYPE_NETWORK) {
+            // If the channel is from network, skip this part since the video and audio tracks
+            // information for channels from network are more reliable in the extractor. Otherwise,
+            // tracks haven't been detected in the extractor. Try again.
+            sendMessage(MSG_RETRY_PLAYBACK, System.identityHashCode(mPlayer));
             return;
         }
         // Since mSurface is volatile, we define a local variable surface to keep the same value
@@ -1269,7 +1421,7 @@
             mPlayer.setSurface(surface);
             mPlayer.setPlayWhenReady(true);
             mPlayer.setVolume(mVolume);
-            if (mChannel != null && !mChannel.hasVideo() && mChannel.hasAudio()) {
+            if (mChannel != null && mPlayer.hasAudio() && !mPlayer.hasVideo()) {
                 notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY);
             } else if (!mReportedWeakSignal) {
                 // Doesn't show buffering during weak signal.
@@ -1286,22 +1438,21 @@
             return;
         }
         mSourceManager.setKeepTuneStatus(true);
-        BufferManager bufferManager = mChannel != null ? mBufferManager : new BufferManager(
-                new DvrStorageManager(new File(getRecordingPath()), false));
-        MpegTsPlayer player = createPlayer(mAudioCapabilities, bufferManager);
+        MpegTsPlayer player = createPlayer(mAudioCapabilities);
         player.setCaptionServiceNumber(Cea708Data.EMPTY_SERVICE_NUMBER);
         player.setVideoEventListener(this);
         player.setCaptionServiceNumber(mCaptionTrack != null ?
                 mCaptionTrack.serviceNumber : Cea708Data.EMPTY_SERVICE_NUMBER);
-        if (!player.prepare(mContext, mChannel, this)) {
+        if (!player.prepare(mContext, mChannel, mHasSoftwareAudioDecoder, this)) {
             mSourceManager.setKeepTuneStatus(false);
             player.release();
             if (!mHandler.hasMessages(MSG_TUNE)) {
                 // When prepare failed, there may be some errors related to hardware. In that
                 // case, retry playback immediately may not help.
                 notifyVideoUnavailable(TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL);
-                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RETRY_PLAYBACK, mPlayer),
-                        PLAYBACK_RETRY_DELAY_MS);
+                Log.i(TAG, "Notify weak signal due to player preparation failure");
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RETRY_PLAYBACK,
+                        System.identityHashCode(mPlayer)), PLAYBACK_RETRY_DELAY_MS);
             }
         } else {
             mPlayer = player;
@@ -1314,7 +1465,7 @@
     private void resetPlayback() {
         long timestamp, oldTimestamp;
         timestamp = SystemClock.elapsedRealtime();
-        stopPlayback();
+        stopPlayback(false);
         stopCaptionTrack();
         if (ENABLE_PROFILER) {
             oldTimestamp = timestamp;
@@ -1336,8 +1487,12 @@
         mRecordingDuration = recording != null ? getDurationForRecording(recording) : null;
         mProgram = null;
         mPrograms = null;
-        mBufferStartTimeMs = mRecordStartTimeMs =
-                (mRecordingId != null) ? 0 : System.currentTimeMillis();
+        if (mRecordingId != null) {
+            // Workaround of b/33298048: set it to 1 instead of 0.
+            mBufferStartTimeMs = mRecordStartTimeMs = 1;
+        } else {
+            mBufferStartTimeMs = mRecordStartTimeMs = System.currentTimeMillis();
+        }
         mLastPositionMs = 0;
         mCaptionTrack = null;
         mHandler.sendEmptyMessage(MSG_PARENTAL_CONTROLS);
@@ -1385,14 +1540,19 @@
             } else {
                 mPlayer.seekTo(mBufferStartTimeMs - mRecordStartTimeMs);
                 mPlaybackParams.setSpeed(1.0f);
-                mPlayer.setAudioTrack(true);
+                mPlayer.setAudioTrackAndClosedCaption(true);
                 return;
             }
         } else if (seekPositionMs > System.currentTimeMillis() - mRecordStartTimeMs) {
-            mPlayer.seekTo(System.currentTimeMillis() - mRecordStartTimeMs);
-            mPlaybackParams.setSpeed(1.0f);
-            mPlayer.setAudioTrack(true);
-            return;
+            // Stops trickplay when FF requested the position later than current position.
+            // If RW trickplay requested the position later than current position,
+            // continue trickplay.
+            if (mPlaybackParams.getSpeed() > 0.0f) {
+                mPlayer.seekTo(System.currentTimeMillis() - mRecordStartTimeMs);
+                mPlaybackParams.setSpeed(1.0f);
+                mPlayer.setAudioTrackAndClosedCaption(true);
+                return;
+            }
         }
 
         long delayForNextSeek = getTrickPlaySeekIntervalMs();
@@ -1414,7 +1574,7 @@
         }
         mPlaybackParams.setSpeed(1.0f);
         mPlayer.setPlayWhenReady(false);
-        mPlayer.setAudioTrack(true);
+        mPlayer.setAudioTrackAndClosedCaption(true);
     }
 
     private void doTimeShiftResume() {
@@ -1422,7 +1582,7 @@
         mHandler.removeMessages(MSG_TRICKPLAY_BY_SEEK);
         mPlaybackParams.setSpeed(1.0f);
         mPlayer.setPlayWhenReady(true);
-        mPlayer.setAudioTrack(true);
+        mPlayer.setAudioTrackAndClosedCaption(true);
     }
 
     private void doTimeShiftSeekTo(long timeMs) {
@@ -1443,14 +1603,14 @@
             doTimeShiftResume();
         } else if (mPlayer.supportSmoothTrickPlay(speed)) {
             mHandler.removeMessages(MSG_TRICKPLAY_BY_SEEK);
-            mPlayer.setAudioTrack(false);
+            mPlayer.setAudioTrackAndClosedCaption(false);
             mPlayer.startSmoothTrickplay(mPlaybackParams);
             mHandler.sendEmptyMessageDelayed(MSG_SMOOTH_TRICKPLAY_MONITOR,
                     TRICKPLAY_MONITOR_INTERVAL_MS);
         } else {
             mHandler.removeMessages(MSG_SMOOTH_TRICKPLAY_MONITOR);
             if (!mHandler.hasMessages(MSG_TRICKPLAY_BY_SEEK)) {
-                mPlayer.setAudioTrack(false);
+                mPlayer.setAudioTrackAndClosedCaption(false);
                 mPlayer.setPlayWhenReady(false);
                 // Initiate trickplay
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_TRICKPLAY_BY_SEEK,
@@ -1525,8 +1685,8 @@
         }
         TvContentRating[] ratings = mTvContentRatingCache
                 .getRatings(currentProgram.getContentRating());
-        if (ratings == null) {
-            return null;
+        if (ratings == null || ratings.length == 0) {
+            ratings = new TvContentRating[] {TvContentRating.UNRATED};
         }
         for (TvContentRating rating : ratings) {
             if (!Objects.equals(mUnblockedContentRating, rating) && mTvInputManager
@@ -1544,15 +1704,15 @@
         }
         mChannelBlocked = channelBlocked;
         if (mChannelBlocked) {
-            mHandler.removeCallbacksAndMessages(null);
-            stopPlayback();
+            clearCallbacksAndMessagesSafely();
+            stopPlayback(true);
             resetTvTracks();
             if (contentRating != null) {
                 mSession.notifyContentBlocked(contentRating);
             }
             mHandler.sendEmptyMessageDelayed(MSG_PARENTAL_CONTROLS, PARENTAL_CONTROLS_INTERVAL_MS);
         } else {
-            mHandler.removeCallbacksAndMessages(null);
+            clearCallbacksAndMessagesSafely();
             resetPlayback();
             mSession.notifyContentAllowed();
             mHandler.sendEmptyMessageDelayed(MSG_RESCHEDULE_PROGRAMS,
@@ -1562,6 +1722,17 @@
         }
     }
 
+    @WorkerThread
+    private void clearCallbacksAndMessagesSafely() {
+        // If MSG_RELEASE is removed, TunerSessionWorker will hang forever.
+        // Do not remove messages, after release is requested from MainThread.
+        synchronized (mReleaseLock) {
+            if (!mReleaseRequested) {
+                mHandler.removeCallbacksAndMessages(null);
+            }
+        }
+    }
+
     private boolean hasEnoughBackwardBuffer() {
         return mPlayer.getCurrentPosition() + BUFFER_UNDERFLOW_BUFFER_MS
                 >= mBufferStartTimeMs - mRecordStartTimeMs;
diff --git a/src/com/android/tv/tuner/tvinput/TunerStorageCleanUpService.java b/src/com/android/tv/tuner/tvinput/TunerStorageCleanUpService.java
index e734b77..6ad00da 100644
--- a/src/com/android/tv/tuner/tvinput/TunerStorageCleanUpService.java
+++ b/src/com/android/tv/tuner/tvinput/TunerStorageCleanUpService.java
@@ -24,6 +24,7 @@
 import android.media.tv.TvContract;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.util.Log;
 
 import com.android.tv.TvApplication;
 import com.android.tv.dvr.DvrStorageStatusManager;
@@ -40,10 +41,17 @@
  * from database.
  */
 public class TunerStorageCleanUpService extends JobService {
+    private static final String TAG = "TunerStorageCleanUpService";
+
     private CleanUpStorageTask mTask;
 
     @Override
     public void onCreate() {
+        if (!TvApplication.getSingletons(this).getTvInputManagerHelper().hasTvInputManager()) {
+            Log.wtf(TAG, "Stopping because device does not have a TvInputManager");
+            this.stopSelf();
+            return;
+        }
         TvApplication.setCurrentRunningProcess(this, false);
         super.onCreate();
         mTask = new CleanUpStorageTask(this, this);
diff --git a/src/com/android/tv/tuner/tvinput/TunerTvInputService.java b/src/com/android/tv/tuner/tvinput/TunerTvInputService.java
index 684ebdb..2725ddf 100644
--- a/src/com/android/tv/tuner/tvinput/TunerTvInputService.java
+++ b/src/com/android/tv/tuner/tvinput/TunerTvInputService.java
@@ -28,9 +28,6 @@
 import com.google.android.exoplayer.audio.AudioCapabilitiesReceiver;
 import com.android.tv.TvApplication;
 import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.tuner.exoplayer.buffer.BufferManager;
-import com.android.tv.tuner.exoplayer.buffer.TrickplayStorageManager;
-import com.android.tv.tuner.util.SystemPropertiesProxy;
 
 import java.util.Collections;
 import java.util.Set;
@@ -45,9 +42,6 @@
     private static final String TAG = "TunerTvInputService";
     private static final boolean DEBUG = false;
 
-    private static final String MAX_BUFFER_SIZE_KEY = "tv.tuner.buffersize_mbytes";
-    private static final int MAX_BUFFER_SIZE_DEF = 2 * 1024;  // 2GB
-    private static final int MIN_BUFFER_SIZE_DEF = 256;  // 256MB
     private static final int DVR_STORAGE_CLEANUP_JOB_ID = 100;
 
     // WeakContainer for {@link TvInputSessionImpl}
@@ -55,17 +49,20 @@
     private ChannelDataManager mChannelDataManager;
     private AudioCapabilitiesReceiver mAudioCapabilitiesReceiver;
     private AudioCapabilities mAudioCapabilities;
-    private BufferManager mBufferManager;
 
     @Override
     public void onCreate() {
+        if (!TvApplication.getSingletons(this).getTvInputManagerHelper().hasTvInputManager()) {
+            Log.wtf(TAG, "Stopping because device does not have a TvInputManager");
+            this.stopSelf();
+            return;
+        }
         TvApplication.setCurrentRunningProcess(this, false);
         super.onCreate();
         if (DEBUG) Log.d(TAG, "onCreate");
         mChannelDataManager = new ChannelDataManager(getApplicationContext());
         mAudioCapabilitiesReceiver = new AudioCapabilitiesReceiver(getApplicationContext(), this);
         mAudioCapabilitiesReceiver.register();
-        mBufferManager = createBufferManager();
         if (CommonFeatures.DVR.isEnabled(this)) {
             JobScheduler jobScheduler =
                     (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
@@ -79,11 +76,6 @@
                 jobScheduler.schedule(job);
             }
         }
-        if (mBufferManager == null) {
-            Log.i(TAG, "Trickplay is disabled");
-        } else {
-            Log.i(TAG, "Trickplay is enabled");
-        }
     }
 
     @Override
@@ -92,9 +84,6 @@
         super.onDestroy();
         mChannelDataManager.release();
         mAudioCapabilitiesReceiver.unregister();
-        if (mBufferManager != null) {
-            mBufferManager.close();
-        }
     }
 
     @Override
@@ -106,8 +95,7 @@
     public Session onCreateSession(String inputId) {
         if (DEBUG) Log.d(TAG, "onCreateSession");
         try {
-            final TunerSession session = new TunerSession(
-                    this, mChannelDataManager, mBufferManager);
+            final TunerSession session = new TunerSession(this, mChannelDataManager);
             mTunerSessions.add(session);
             session.setAudioCapabilities(mAudioCapabilities);
             session.setOverlayViewEnabled(true);
@@ -129,17 +117,6 @@
         }
     }
 
-    private BufferManager createBufferManager() {
-        int maxBufferSizeMb =
-                SystemPropertiesProxy.getInt(MAX_BUFFER_SIZE_KEY, MAX_BUFFER_SIZE_DEF);
-        if (maxBufferSizeMb >= MIN_BUFFER_SIZE_DEF) {
-            return new BufferManager(
-                    new TrickplayStorageManager(getApplicationContext(), getCacheDir(),
-                            1024L * 1024 * maxBufferSizeMb));
-        }
-        return null;
-    }
-
     public static String getInputId(Context context) {
         return TvContract.buildInputId(new ComponentName(context, TunerTvInputService.class));
     }
diff --git a/src/com/android/tv/tuner/util/PostalCodeUtils.java b/src/com/android/tv/tuner/util/PostalCodeUtils.java
new file mode 100644
index 0000000..9eb689a
--- /dev/null
+++ b/src/com/android/tv/tuner/util/PostalCodeUtils.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2017 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.tuner.util;
+
+import android.content.Context;
+import android.location.Address;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.text.TextUtils;
+import android.util.Log;
+import com.android.tv.tuner.TunerPreferences;
+import com.android.tv.util.LocationUtils;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * A utility class to update, get, and set the last known postal or zip code.
+ */
+public class PostalCodeUtils {
+    private static final String TAG = "PostalCodeUtils";
+
+    // Postcode formats, where A signifies a letter and 9 a digit:
+    // US zip code format: 99999
+    private static final String POSTCODE_REGEX_US = "^(\\d{5})";
+    // UK postcode district formats: A9, A99, AA9, AA99
+    // Full UK postcode format: Postcode District + space + 9AA
+    // Should be able to handle both postcode district and full postcode
+    private static final String POSTCODE_REGEX_GB =
+            "^([A-Z][A-Z]?[0-9][0-9A-Z]?)( ?[0-9][A-Z]{2})?$";
+    private static final String POSTCODE_REGEX_GB_GIR = "^GIR( ?0AA)?$"; // special UK postcode
+
+    private static final Map<String, Pattern> REGION_PATTERN = new HashMap<>();
+    private static final Map<String, Integer> REGION_MAX_LENGTH = new HashMap<>();
+
+    static {
+        REGION_PATTERN.put(Locale.US.getCountry(), Pattern.compile(POSTCODE_REGEX_US));
+        REGION_PATTERN.put(
+                Locale.UK.getCountry(),
+                Pattern.compile(POSTCODE_REGEX_GB + "|" + POSTCODE_REGEX_GB_GIR));
+        REGION_MAX_LENGTH.put(Locale.US.getCountry(), 5);
+        REGION_MAX_LENGTH.put(Locale.UK.getCountry(), 8);
+    }
+
+    // The longest postcode number is 10-character-long.
+    // Use a larger number to accommodate future changes.
+    private static final int DEFAULT_MAX_LENGTH = 16;
+
+    /** Returns {@code true} if postal code has been changed */
+    public static boolean updatePostalCode(Context context)
+            throws IOException, SecurityException, NoPostalCodeException {
+        String postalCode = getPostalCode(context);
+        String lastPostalCode = getLastPostalCode(context);
+        if (TextUtils.isEmpty(postalCode)) {
+            if (TextUtils.isEmpty(lastPostalCode)) {
+                throw new NoPostalCodeException();
+            }
+        } else if (!TextUtils.equals(postalCode, lastPostalCode)) {
+            setLastPostalCode(context, postalCode);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Gets the last stored postal or zip code, which might be decided by {@link LocationUtils} or
+     * input by users.
+     */
+    public static String getLastPostalCode(Context context) {
+        return TunerPreferences.getLastPostalCode(context);
+    }
+
+    /**
+     * Sets the last stored postal or zip code. This method will overwrite the value written by
+     * calling {@link #updatePostalCode(Context)}.
+     */
+    public static void setLastPostalCode(Context context, String postalCode) {
+        Log.i(TAG, "Set Postal Code:" + postalCode);
+        TunerPreferences.setLastPostalCode(context, postalCode);
+    }
+
+    @Nullable
+    private static String getPostalCode(Context context) throws IOException, SecurityException {
+        Address address = LocationUtils.getCurrentAddress(context);
+        if (address != null) {
+            Log.i(TAG, "Current country and postal code is " + address.getCountryName() + ", "
+                    + address.getPostalCode());
+            return address.getPostalCode();
+        }
+        return null;
+    }
+
+    /** An {@link java.lang.Exception} class to notify no valid postal or zip code is available. */
+    public static class NoPostalCodeException extends Exception {
+        public NoPostalCodeException() {
+        }
+    }
+
+    /**
+     * Checks whether a postcode matches the format of the specific region.
+     *
+     * @return {@code false} if the region is supported and the postcode doesn't match; {@code true}
+     *     otherwise
+     */
+    public static boolean matches(@NonNull CharSequence postcode, @NonNull String region) {
+        Pattern pattern = REGION_PATTERN.get(region.toUpperCase());
+        return pattern == null || pattern.matcher(postcode).matches();
+    }
+
+    /**
+     * Gets the largest possible postcode length in the region.
+     *
+     * @return maximum postcode length if the region is supported; {@link #DEFAULT_MAX_LENGTH}
+     *     otherwise
+     */
+    public static int getRegionMaxLength(Context context) {
+        Integer maxLength =
+                REGION_MAX_LENGTH.get(LocationUtils.getCurrentCountry(context).toUpperCase());
+        return maxLength == null ? DEFAULT_MAX_LENGTH : maxLength;
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/tv/tuner/util/SystemPropertiesProxy.java b/src/com/android/tv/tuner/util/SystemPropertiesProxy.java
index 62a6436..2817ccb 100644
--- a/src/com/android/tv/tuner/util/SystemPropertiesProxy.java
+++ b/src/com/android/tv/tuner/util/SystemPropertiesProxy.java
@@ -58,4 +58,20 @@
         }
         return def;
     }
+
+    public static String getString(String key, String def) throws IllegalArgumentException {
+        try {
+            Class SystemPropertiesClass = Class.forName("android.os.SystemProperties");
+            Method getIntMethod =
+                    SystemPropertiesClass.getDeclaredMethod("get", String.class, String.class);
+            getIntMethod.setAccessible(true);
+            return (String) getIntMethod.invoke(SystemPropertiesClass, key, def);
+        } catch (InvocationTargetException
+                | IllegalAccessException
+                | NoSuchMethodException
+                | ClassNotFoundException e) {
+            Log.e(TAG, "Failed to invoke SystemProperties.get()", e);
+        }
+        return def;
+    }
 }
diff --git a/src/com/android/tv/tuner/util/TunerInputInfoUtils.java b/src/com/android/tv/tuner/util/TunerInputInfoUtils.java
index 5c411f6..f421bf1 100644
--- a/src/com/android/tv/tuner/util/TunerInputInfoUtils.java
+++ b/src/com/android/tv/tuner/util/TunerInputInfoUtils.java
@@ -21,10 +21,11 @@
 import android.content.Context;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
+import android.os.AsyncTask;
 import android.os.Build;
 import android.support.annotation.Nullable;
-import android.support.v4.os.BuildCompat;
 import android.util.Log;
+import android.util.Pair;
 
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.tuner.R;
@@ -43,23 +44,31 @@
      */
     @Nullable
     @TargetApi(Build.VERSION_CODES.N)
-    public static TvInputInfo buildTunerInputInfo(Context context, boolean fromBuiltInTuner) {
-        int numOfDevices = TunerHal.getTunerCount(context);
-        if (numOfDevices == 0) {
+    public static TvInputInfo buildTunerInputInfo(Context context) {
+        Pair<Integer, Integer> tunerTypeAndCount = TunerHal.getTunerTypeAndCount(context);
+        if (tunerTypeAndCount.first == null || tunerTypeAndCount.second == 0) {
             return null;
         }
-        TvInputInfo.Builder builder = new TvInputInfo.Builder(context, new ComponentName(context,
-                TunerTvInputService.class));
-        if (fromBuiltInTuner) {
-            builder.setLabel(R.string.bt_app_name);
-        } else {
-            builder.setLabel(R.string.ut_app_name);
+        int inputLabelId = 0;
+        switch (tunerTypeAndCount.first) {
+            case TunerHal.TUNER_TYPE_BUILT_IN:
+                inputLabelId = R.string.bt_app_name;
+                break;
+            case TunerHal.TUNER_TYPE_USB:
+                inputLabelId = R.string.ut_app_name;
+                break;
+            case TunerHal.TUNER_TYPE_NETWORK:
+                inputLabelId = R.string.nt_app_name;
+                break;
         }
         try {
-            return builder.setCanRecord(CommonFeatures.DVR.isEnabled(context))
-                    .setTunerCount(numOfDevices)
+            TvInputInfo.Builder builder = new TvInputInfo.Builder(context,
+                    new ComponentName(context, TunerTvInputService.class));
+            return builder.setLabel(inputLabelId)
+                    .setCanRecord(CommonFeatures.DVR.isEnabled(context))
+                    .setTunerCount(tunerTypeAndCount.second)
                     .build();
-        } catch (NullPointerException e) {
+        } catch (IllegalArgumentException | NullPointerException e) {
             // TunerTvInputService is not enabled.
             return null;
         }
@@ -71,30 +80,36 @@
      * @param context {@link Context} instance
      */
     public static void updateTunerInputInfo(Context context) {
-        if (BuildCompat.isAtLeastN()) {
-            if (DEBUG) Log.d(TAG, "updateTunerInputInfo()");
-            TvInputInfo info = buildTunerInputInfo(context, isBuiltInTuner(context));
-            if (info != null) {
-                ((TvInputManager) context.getSystemService(Context.TV_INPUT_SERVICE))
-                        .updateTvInputInfo(info);
-                if (DEBUG) {
-                    Log.d(TAG, "TvInputInfo [" + info.loadLabel(context)
-                            + "] updated: " + info.toString());
+        final Context appContext = context.getApplicationContext();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            new AsyncTask<Void, Void, TvInputInfo>() {
+                @Override
+                protected TvInputInfo doInBackground(Void... params) {
+                    if (DEBUG) Log.d(TAG, "updateTunerInputInfo()");
+                    return buildTunerInputInfo(appContext);
                 }
-            } else {
-                if (DEBUG) {
-                    Log.d(TAG, "Updating tuner input's info failed. Input is not ready yet.");
+
+                @Override
+                @TargetApi(Build.VERSION_CODES.N)
+                protected void onPostExecute(TvInputInfo info) {
+                    if (info != null) {
+                        ((TvInputManager) appContext.getSystemService(Context.TV_INPUT_SERVICE))
+                                .updateTvInputInfo(info);
+                        if (DEBUG) {
+                            Log.d(
+                                    TAG,
+                                    "TvInputInfo ["
+                                            + info.loadLabel(appContext)
+                                            + "] updated: "
+                                            + info.toString());
+                        }
+                    } else {
+                        if (DEBUG) {
+                            Log.d(TAG, "Updating tuner input info failed. Input is not ready yet.");
+                        }
+                    }
                 }
-            }
+            }.execute();
         }
     }
-
-    /**
-     * Returns if the current tuner service is for a built-in tuner.
-     *
-     * @param context {@link Context} instance
-     */
-    public static boolean isBuiltInTuner(Context context) {
-        return TunerHal.getTunerType(context) == TunerHal.TUNER_TYPE_BUILT_IN;
-    }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/ui/AppLayerTvView.java b/src/com/android/tv/ui/AppLayerTvView.java
index 09acb36..625014e 100644
--- a/src/com/android/tv/ui/AppLayerTvView.java
+++ b/src/com/android/tv/ui/AppLayerTvView.java
@@ -22,7 +22,8 @@
 import android.view.SurfaceView;
 import android.view.View;
 
-import com.android.tv.experiments.Experiments;
+import com.android.tv.util.Debug;
+import com.android.tv.util.Utils;
 
 /**
  * A TvView class for application layer when multiple windows are being used in the app.
@@ -55,8 +56,17 @@
     public void onViewAdded(View child) {
         if (child instanceof SurfaceView) {
             // Note: See b/29118070 for detail.
-            ((SurfaceView) child).setSecure(!Experiments.ENABLE_DEVELOPER_FEATURES.get());
+            ((SurfaceView) child).setSecure(!Utils.isDeveloper());
         }
         super.onViewAdded(child);
     }
+
+    @Override
+    public void getLocationOnScreen(int[] outLocation) {
+        super.getLocationOnScreen(outLocation);
+
+        // The TvView.MySessionCallback.onSessionCreated() will call this method indirectly.
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+                "AppLayerTvView.getLocationOnScreen, session created");
+    }
 }
diff --git a/src/com/android/tv/ui/BlockScreenView.java b/src/com/android/tv/ui/BlockScreenView.java
index 52b9389..09c167c 100644
--- a/src/com/android/tv/ui/BlockScreenView.java
+++ b/src/com/android/tv/ui/BlockScreenView.java
@@ -21,32 +21,37 @@
 import android.animation.AnimatorInflater;
 import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.View;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
-import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.tv.R;
 import com.android.tv.ui.TunableTvView.BlockScreenType;
 
-public class BlockScreenView extends LinearLayout {
+public class BlockScreenView extends FrameLayout {
     private View mContainerView;
     private View mImageContainer;
-    private ImageView mNormalImageView;
-    private ImageView mShrunkenImageView;
+    private ImageView mNormalLockIconView;
+    private ImageView mShrunkenLockIconView;
     private View mSpace;
-    private TextView mTextView;
+    private TextView mBlockingInfoTextView;
+    private ImageView mBackgroundImageView;
 
     private final int mSpacingNormal;
     private final int mSpacingShrunken;
 
-    // Animators used for fade in/out of block screen icon.
-    private Animator mFadeIn;
+    // Animator used to fade out the whole block screen.
     private Animator mFadeOut;
 
+    // Animators used to fade in/out the block screen icon and info text.
+    private Animator mInfoFadeIn;
+    private Animator mInfoFadeOut;
+
     public BlockScreenView(Context context) {
         this(context, null, 0);
     }
@@ -68,21 +73,32 @@
         super.onFinishInflate();
         mContainerView = findViewById(R.id.block_screen_container);
         mImageContainer = findViewById(R.id.image_container);
-        mNormalImageView = (ImageView) findViewById(R.id.block_screen_icon);
-        mShrunkenImageView = (ImageView) findViewById(R.id.block_screen_shrunken_icon);
+        mNormalLockIconView = (ImageView) findViewById(R.id.block_screen_icon);
+        mShrunkenLockIconView = (ImageView) findViewById(R.id.block_screen_shrunken_icon);
         mSpace = findViewById(R.id.space);
-        mTextView = (TextView) findViewById(R.id.block_screen_text);
-        mFadeIn = AnimatorInflater.loadAnimator(getContext(),
-                R.animator.tvview_block_screen_fade_in);
-        mFadeIn.setTarget(mContainerView);
+        mBlockingInfoTextView = (TextView) findViewById(R.id.block_screen_text);
+        mBackgroundImageView = (ImageView) findViewById(R.id.background_image);
         mFadeOut = AnimatorInflater.loadAnimator(getContext(),
                 R.animator.tvview_block_screen_fade_out);
-        mFadeOut.setTarget(mContainerView);
+        mFadeOut.setTarget(this);
         mFadeOut.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
+                setVisibility(GONE);
+                setBackgroundImage(null);
+                setAlpha(1.0f);
+            }
+        });
+        mInfoFadeIn = AnimatorInflater.loadAnimator(getContext(),
+                R.animator.tvview_block_screen_fade_in);
+        mInfoFadeIn.setTarget(mContainerView);
+        mInfoFadeOut = AnimatorInflater.loadAnimator(getContext(),
+                R.animator.tvview_block_screen_fade_out);
+        mInfoFadeOut.setTarget(mContainerView);
+        mInfoFadeOut.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
                 mContainerView.setVisibility(GONE);
-                mContainerView.setAlpha(1f);
             }
         });
     }
@@ -90,31 +106,23 @@
     /**
      * Sets the normal image.
      */
-    public void setImage(int resId) {
-        mNormalImageView.setImageResource(resId);
+    public void setIconImage(int resId) {
+        mNormalLockIconView.setImageResource(resId);
         updateSpaceVisibility();
     }
 
     /**
      * Sets the scale type of the normal image.
      */
-    public void setScaleType(ScaleType scaleType) {
-        mNormalImageView.setScaleType(scaleType);
-        updateSpaceVisibility();
-    }
-
-    /**
-     * Sets the shrunken image.
-     */
-    public void setShrunkenImage(int resId) {
-        mShrunkenImageView.setImageResource(resId);
+    public void setIconScaleType(ScaleType scaleType) {
+        mNormalLockIconView.setScaleType(scaleType);
         updateSpaceVisibility();
     }
 
     /**
      * Show or hide the image of this view.
      */
-    public void setImageVisibility(boolean visible) {
+    public void setIconVisibility(boolean visible) {
         mImageContainer.setVisibility(visible ? VISIBLE : GONE);
         updateSpaceVisibility();
     }
@@ -122,21 +130,30 @@
     /**
      * Sets the text message.
      */
-    public void setText(int resId) {
-        mTextView.setText(resId);
+    public void setInfoText(int resId) {
+        mBlockingInfoTextView.setText(resId);
         updateSpaceVisibility();
     }
 
     /**
      * Sets the text message.
      */
-    public void setText(String text) {
-        mTextView.setText(text);
+    public void setInfoText(String text) {
+        mBlockingInfoTextView.setText(text);
         updateSpaceVisibility();
     }
 
+    /**
+     * Sets the background image should be displayed in the block screen view. Passes {@code null}
+     * to remove the currently displayed background image.
+     */
+    public void setBackgroundImage(Drawable backgroundImage) {
+        mBackgroundImageView.setVisibility(backgroundImage == null ? GONE : VISIBLE);
+        mBackgroundImageView.setImageDrawable(backgroundImage);
+    }
+
     private void updateSpaceVisibility() {
-        if (isImageViewVisible() && isTextViewVisible(mTextView)) {
+        if (isImageViewVisible() && isTextViewVisible(mBlockingInfoTextView)) {
             mSpace.setVisibility(VISIBLE);
         } else {
             mSpace.setVisibility(GONE);
@@ -145,7 +162,8 @@
 
     private boolean isImageViewVisible() {
         return mImageContainer.getVisibility() == VISIBLE
-                && (isImageViewVisible(mNormalImageView) || isImageViewVisible(mShrunkenImageView));
+                && (isImageViewVisible(mNormalLockIconView)
+                        || isImageViewVisible(mShrunkenLockIconView));
     }
 
     private static boolean isImageViewVisible(ImageView imageView) {
@@ -177,37 +195,39 @@
                     mContainerView.setVisibility(GONE);
                     break;
                 case TunableTvView.BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
-                    mNormalImageView.setVisibility(GONE);
-                    mShrunkenImageView.setVisibility(VISIBLE);
+                    mNormalLockIconView.setVisibility(GONE);
+                    mShrunkenLockIconView.setVisibility(VISIBLE);
                     mContainerView.setVisibility(VISIBLE);
+                    mContainerView.setAlpha(1.0f);
                     break;
                 case TunableTvView.BLOCK_SCREEN_TYPE_NORMAL:
-                    mNormalImageView.setVisibility(VISIBLE);
-                    mShrunkenImageView.setVisibility(GONE);
+                    mNormalLockIconView.setVisibility(VISIBLE);
+                    mShrunkenLockIconView.setVisibility(GONE);
                     mContainerView.setVisibility(VISIBLE);
+                    mContainerView.setAlpha(1.0f);
                     break;
             }
         } else {
             switch (blockScreenType) {
                 case TunableTvView.BLOCK_SCREEN_TYPE_NO_UI:
                     if (mContainerView.getVisibility() == VISIBLE) {
-                        mFadeOut.start();
+                        mInfoFadeOut.start();
                     }
                     break;
                 case TunableTvView.BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
-                    mNormalImageView.setVisibility(GONE);
-                    mShrunkenImageView.setVisibility(VISIBLE);
-                    mContainerView.setVisibility(VISIBLE);
+                    mNormalLockIconView.setVisibility(GONE);
+                    mShrunkenLockIconView.setVisibility(VISIBLE);
                     if (mContainerView.getVisibility() == GONE) {
-                        mFadeIn.start();
+                        mContainerView.setVisibility(VISIBLE);
+                        mInfoFadeIn.start();
                     }
                     break;
                 case TunableTvView.BLOCK_SCREEN_TYPE_NORMAL:
-                    mNormalImageView.setVisibility(VISIBLE);
-                    mShrunkenImageView.setVisibility(GONE);
-                    mContainerView.setVisibility(VISIBLE);
+                    mNormalLockIconView.setVisibility(VISIBLE);
+                    mShrunkenLockIconView.setVisibility(GONE);
                     if (mContainerView.getVisibility() == GONE) {
-                        mFadeIn.start();
+                        mContainerView.setVisibility(VISIBLE);
+                        mInfoFadeIn.start();
                     }
                     break;
             }
@@ -216,26 +236,33 @@
     }
 
     /**
-     * Scales the contents view by the given {@code scale}.
+     * Adds a listener to the fade-in animation of info text and icons of the block screen.
      */
-    public void scaleContainerView(float scale) {
-        mContainerView.setScaleX(scale);
-        mContainerView.setScaleY(scale);
+    public void addInfoFadeInAnimationListener(AnimatorListener listener) {
+        mInfoFadeIn.addListener(listener);
     }
 
-    public void addFadeOutAnimationListener(AnimatorListener listener) {
-        mFadeOut.addListener(listener);
+    /**
+     * Fades out the block screen.
+     */
+    public void fadeOut() {
+        if (getVisibility() == VISIBLE && !mFadeOut.isStarted()) {
+            mFadeOut.start();
+        }
     }
 
     /**
      * Ends the currently running animations.
      */
     public void endAnimations() {
-        if (mFadeIn != null && mFadeIn.isRunning()) {
-            mFadeIn.end();
-        }
         if (mFadeOut != null && mFadeOut.isRunning()) {
             mFadeOut.end();
         }
+        if (mInfoFadeIn != null && mInfoFadeIn.isRunning()) {
+            mInfoFadeIn.end();
+        }
+        if (mInfoFadeOut != null && mInfoFadeOut.isRunning()) {
+            mInfoFadeOut.end();
+        }
     }
 }
diff --git a/src/com/android/tv/ui/ChannelBannerView.java b/src/com/android/tv/ui/ChannelBannerView.java
index 3cf4de8..a5d897f 100644
--- a/src/com/android/tv/ui/ChannelBannerView.java
+++ b/src/com/android/tv/ui/ChannelBannerView.java
@@ -23,12 +23,9 @@
 import android.animation.ValueAnimator;
 import android.content.Context;
 import android.content.res.Resources;
-import android.database.ContentObserver;
 import android.graphics.Bitmap;
 import android.media.tv.TvContentRating;
-import android.media.tv.TvContract;
 import android.media.tv.TvInputInfo;
-import android.net.Uri;
 import android.os.Handler;
 import android.support.annotation.Nullable;
 import android.text.Spannable;
@@ -52,12 +49,13 @@
 import com.android.tv.MainActivity;
 import com.android.tv.R;
 import com.android.tv.TvApplication;
+import com.android.tv.common.SoftPreconditions;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.data.Channel;
 import com.android.tv.data.Program;
 import com.android.tv.data.StreamInfo;
 import com.android.tv.dvr.DvrManager;
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.parental.ContentRatingsManager;
 import com.android.tv.util.ImageCache;
 import com.android.tv.util.ImageLoader;
@@ -65,10 +63,6 @@
 import com.android.tv.util.ImageLoader.LoadTvInputLogoTask;
 import com.android.tv.util.Utils;
 
-import junit.framework.Assert;
-
-import java.util.Objects;
-
 /**
  * A view to render channel banner.
  */
@@ -98,8 +92,8 @@
 
     private static final String EMPTY_STRING = "";
 
-    private static Program sNoProgram;
-    private static Program sLockedChannelProgram;
+    private Program mNoProgram;
+    private Program mLockedChannelProgram;
     private static String sClosedCaptionMark;
 
     private final MainActivity mMainActivity;
@@ -123,6 +117,7 @@
     private String mProgramDescriptionText;
     private View mAnchorView;
     private Channel mCurrentChannel;
+    private boolean mCurrentChannelLogoExists;
     private Program mLastUpdatedProgram;
     private final Handler mHandler = new Handler();
     private final DvrManager mDvrManager;
@@ -130,6 +125,7 @@
     private TvContentRating mBlockingContentRating;
 
     private int mLockType;
+    private boolean mUpdateOnTune;
 
     private Animator mResizeAnimator;
     private int mCurrentHeight;
@@ -178,24 +174,6 @@
         }
     };
 
-    private final ContentObserver mProgramUpdateObserver = new ContentObserver(mHandler) {
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            // TODO: This {@code uri} argument may be a program which is not related to this
-            // channel. Consider adding channel id as a parameter of program URI to avoid
-            // unnecessary update.
-            mHandler.post(mProgramUpdateRunnable);
-        }
-    };
-
-    private final Runnable mProgramUpdateRunnable = new Runnable() {
-        @Override
-        public void run() {
-            removeCallbacks(this);
-            updateViews(null);
-        }
-    };
-
     public ChannelBannerView(Context context) {
         this(context, null);
     }
@@ -243,39 +221,20 @@
         mContentRatingsManager = TvApplication.getSingletons(getContext())
                 .getTvInputManagerHelper().getContentRatingsManager();
 
-        if (sNoProgram == null) {
-            sNoProgram = new Program.Builder()
-                    .setTitle(context.getString(R.string.channel_banner_no_title))
-                    .setDescription(EMPTY_STRING)
-                    .build();
-        }
-        if (sLockedChannelProgram == null){
-            sLockedChannelProgram = new Program.Builder()
-                    .setTitle(context.getString(R.string.channel_banner_locked_channel_title))
-                    .setDescription(EMPTY_STRING)
-                    .build();
-        }
+        mNoProgram = new Program.Builder()
+                .setTitle(context.getString(R.string.channel_banner_no_title))
+                .setDescription(EMPTY_STRING)
+                .build();
+        mLockedChannelProgram = new Program.Builder()
+                .setTitle(context.getString(R.string.channel_banner_locked_channel_title))
+                .setDescription(EMPTY_STRING)
+                .build();
         if (sClosedCaptionMark == null) {
             sClosedCaptionMark = context.getString(R.string.closed_caption);
         }
     }
 
     @Override
-    protected void onAttachedToWindow() {
-        if (DEBUG) Log.d(TAG, "onAttachedToWindow");
-        super.onAttachedToWindow();
-        getContext().getContentResolver().registerContentObserver(TvContract.Programs.CONTENT_URI,
-                true, mProgramUpdateObserver);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        if (DEBUG) Log.d(TAG, "onDetachedToWindow");
-        getContext().getContentResolver().unregisterContentObserver(mProgramUpdateObserver);
-        super.onDetachedFromWindow();
-    }
-
-    @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
 
@@ -345,19 +304,17 @@
      * Set new lock type.
      *
      * @param lockType Any of LOCK_NONE, LOCK_PROGRAM_DETAIL, or LOCK_CHANNEL_INFO.
-     * @return {@code true} only if lock type is changed
+     * @return the previous lock type of the channel banner.
      * @throws IllegalArgumentException if lockType is invalid.
      */
-    public boolean setLockType(int lockType) {
+    public int setLockType(int lockType) {
         if (lockType != LOCK_NONE && lockType != LOCK_CHANNEL_INFO
                 && lockType != LOCK_PROGRAM_DETAIL) {
             throw new IllegalArgumentException("No such lock type " + lockType);
         }
-        if (mLockType != lockType) {
-            mLockType = lockType;
-            return true;
-        }
-        return false;
+        int previousLockType = mLockType;
+        mLockType = lockType;
+        return previousLockType;
     }
 
     /**
@@ -372,31 +329,34 @@
     /**
      * Update channel banner view.
      *
-     * @param info A StreamInfo that includes stream information.
-     * If it's {@code null}, only program information will be updated.
+     * @param updateOnTune {@false} denotes the channel banner is updated due to other reasons than
+     *                              tuning. The channel info will not be updated in this case.
      */
-    public void updateViews(StreamInfo info) {
+    public void updateViews(boolean updateOnTune) {
         resetAnimationEffects();
-        Channel channel = mMainActivity.getCurrentChannel();
-        if (!Objects.equals(mCurrentChannel, channel)) {
-            mBlockingContentRating = null;
+        mChannelView.setVisibility(VISIBLE);
+        mUpdateOnTune = updateOnTune;
+        if (mUpdateOnTune) {
             if (isShown()) {
                 scheduleHide();
             }
-        }
-        mCurrentChannel = channel;
-        mChannelView.setVisibility(VISIBLE);
-        if (info != null) {
-            // If the current channels between ChannelTuner and TvView are different,
-            // the stream information should not be seen.
-            updateStreamInfo(channel != null && channel.equals(info.getCurrentChannel()) ? info
-                    : null);
+            mBlockingContentRating = null;
+            mCurrentChannel = mMainActivity.getCurrentChannel();
+            mCurrentChannelLogoExists =
+                    mCurrentChannel != null && mCurrentChannel.channelLogoExists();
+            updateStreamInfo(null);
             updateChannelInfo();
         }
         updateProgramInfo(mMainActivity.getCurrentProgram());
+        mUpdateOnTune = false;
     }
 
-    private void updateStreamInfo(StreamInfo info) {
+    /**
+     * Update channel banner view with stream info.
+     *
+     * @param info A StreamInfo that includes stream information.
+     */
+    public void updateStreamInfo(StreamInfo info) {
         // Update stream information in a channel.
         if (mLockType != LOCK_CHANNEL_INFO && info != null) {
             updateText(mClosedCaptionTextView, info.hasClosedCaption() ? sClosedCaptionMark
@@ -414,9 +374,6 @@
             mAspectRatioTextView.setVisibility(View.GONE);
             mResolutionTextView.setVisibility(View.GONE);
             mAudioChannelTextView.setVisibility(View.GONE);
-            for (int i = 0; i < DISPLAYED_CONTENT_RATINGS_COUNT; i++) {
-                mContentRatingsTextViews[i].setVisibility(View.GONE);
-            }
         }
     }
 
@@ -467,7 +424,7 @@
         }
         mChannelLogoImageView.setImageBitmap(null);
         mChannelLogoImageView.setVisibility(View.GONE);
-        if (mCurrentChannel != null) {
+        if (mCurrentChannel != null && mCurrentChannelLogoExists) {
             mCurrentChannel.loadBitmap(getContext(), Channel.LOAD_IMAGE_TYPE_CHANNEL_LOGO,
                     mChannelLogoImageViewWidth, mChannelLogoImageViewHeight,
                     createChannelLogoCallback(this, mCurrentChannel));
@@ -550,8 +507,9 @@
 
         if (mResizeAnimator == null) {
             String description = mProgramDescriptionTextView.getText().toString();
-            boolean needFadeAnimation = !description.equals(mProgramDescriptionText);
-            updateBannerHeight(needFadeAnimation);
+            boolean programDescriptionNeedFadeAnimation =
+                    !description.equals(mProgramDescriptionText) && !mUpdateOnTune;
+            updateBannerHeight(programDescriptionNeedFadeAnimation);
         } else {
             mProgramInfoUpdatePendingByResizing = true;
         }
@@ -559,9 +517,9 @@
 
     private void updateProgramInfo(Program program) {
         if (mLockType == LOCK_CHANNEL_INFO) {
-            program = sLockedChannelProgram;
+            program = mLockedChannelProgram;
         } else if (program == null || !program.isValid() || TextUtils.isEmpty(program.getTitle())) {
-            program = sNoProgram;
+            program = mNoProgram;
         }
 
         if (mLastUpdatedProgram == null
@@ -590,9 +548,9 @@
                 mProgramDescriptionText = program.getDescription();
             }
             String description = mProgramDescriptionTextView.getText().toString();
-            boolean needFadeAnimation = isProgramChanged
-                    || !description.equals(mProgramDescriptionText);
-            updateBannerHeight(needFadeAnimation);
+            boolean programDescriptionNeedFadeAnimation = (isProgramChanged
+                    || !description.equals(mProgramDescriptionText)) && !mUpdateOnTune;
+            updateBannerHeight(programDescriptionNeedFadeAnimation);
         } else {
             mProgramInfoUpdatePendingByResizing = true;
         }
@@ -603,7 +561,7 @@
         if (program == null) {
             return;
         }
-        updateProgramTextView(program == sLockedChannelProgram, program.getTitle(),
+        updateProgramTextView(program == mLockedChannelProgram, program.getTitle(),
                 program.getEpisodeDisplayTitle(getContext()));
     }
 
@@ -630,9 +588,8 @@
                     Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
             mProgramTextView.setText(text);
         }
-        int width = mProgramDescriptionTextViewWidth
-                - ((mChannelLogoImageView.getVisibility() != View.VISIBLE)
-                ? 0 : mChannelLogoImageViewWidth + mChannelLogoImageViewMarginStart);
+        int width = mProgramDescriptionTextViewWidth + (mCurrentChannelLogoExists ?
+                0 : mChannelLogoImageViewWidth + mChannelLogoImageViewMarginStart);
         ViewGroup.LayoutParams lp = mProgramTextView.getLayoutParams();
         lp.width = width;
         mProgramTextView.setLayoutParams(lp);
@@ -655,23 +612,32 @@
     }
 
     private void updateProgramRatings(Program program) {
-        if (mBlockingContentRating != null) {
-            mContentRatingsTextViews[0].setText(
-                    mContentRatingsManager.getDisplayNameForRating(mBlockingContentRating));
-            mContentRatingsTextViews[0].setVisibility(View.VISIBLE);
+        if (mLockType == LOCK_CHANNEL_INFO) {
+            for (int i = 0; i < DISPLAYED_CONTENT_RATINGS_COUNT; i++) {
+                mContentRatingsTextViews[i].setVisibility(View.GONE);
+            }
+        } else if (mBlockingContentRating != null) {
+            String displayNameForRating =
+                    mContentRatingsManager.getDisplayNameForRating(mBlockingContentRating);
+            if (!TextUtils.isEmpty(displayNameForRating)) {
+                mContentRatingsTextViews[0].setText(displayNameForRating);
+                mContentRatingsTextViews[0].setVisibility(View.VISIBLE);
+            } else {
+                mContentRatingsTextViews[0].setVisibility(View.GONE);
+            }
             for (int i = 1; i < DISPLAYED_CONTENT_RATINGS_COUNT; i++) {
                 mContentRatingsTextViews[i].setVisibility(View.GONE);
             }
-            return;
-        }
-        TvContentRating[] ratings = (program == null) ? null : program.getContentRatings();
-        for (int i = 0; i < DISPLAYED_CONTENT_RATINGS_COUNT; i++) {
-            if (ratings == null || ratings.length <= i) {
-                mContentRatingsTextViews[i].setVisibility(View.GONE);
-            } else {
-                mContentRatingsTextViews[i].setText(
-                        mContentRatingsManager.getDisplayNameForRating(ratings[i]));
-                mContentRatingsTextViews[i].setVisibility(View.VISIBLE);
+        } else {
+            TvContentRating[] ratings = (program == null) ? null : program.getContentRatings();
+            for (int i = 0; i < DISPLAYED_CONTENT_RATINGS_COUNT; i++) {
+                if (ratings == null || ratings.length <= i) {
+                    mContentRatingsTextViews[i].setVisibility(View.GONE);
+                } else {
+                    mContentRatingsTextViews[i].setText(
+                            mContentRatingsManager.getDisplayNameForRating(ratings[i]));
+                    mContentRatingsTextViews[i].setVisibility(View.VISIBLE);
+                }
             }
         }
     }
@@ -769,8 +735,8 @@
         mLastUpdatedProgram = program;
     }
 
-    private void updateBannerHeight(boolean needFadeAnimation) {
-        Assert.assertNull(mResizeAnimator);
+    private void updateBannerHeight(boolean needProgramDescriptionFadeAnimation) {
+        SoftPreconditions.checkState(mResizeAnimator == null);
         // Need to measure the layout height with the new description text.
         CharSequence oldDescription = mProgramDescriptionTextView.getText();
         mProgramDescriptionTextView.setText(mProgramDescriptionText);
@@ -785,12 +751,13 @@
                 layoutParams.height = targetHeight;
                 setLayoutParams(layoutParams);
             }
-        } else if (mCurrentHeight != targetHeight || needFadeAnimation) {
+        } else if (mCurrentHeight != targetHeight || needProgramDescriptionFadeAnimation) {
             // Restore description text for fade in/out animation.
-            if (needFadeAnimation) {
+            if (needProgramDescriptionFadeAnimation) {
                 mProgramDescriptionTextView.setText(oldDescription);
             }
-            mResizeAnimator = createResizeAnimator(targetHeight, needFadeAnimation);
+            mResizeAnimator =
+                    createResizeAnimator(targetHeight, needProgramDescriptionFadeAnimation);
             mResizeAnimator.start();
         }
     }
diff --git a/src/com/android/tv/ui/KeypadChannelSwitchView.java b/src/com/android/tv/ui/KeypadChannelSwitchView.java
index abc05ba..ac5d841 100644
--- a/src/com/android/tv/ui/KeypadChannelSwitchView.java
+++ b/src/com/android/tv/ui/KeypadChannelSwitchView.java
@@ -39,7 +39,7 @@
 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.Tracker;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
diff --git a/src/com/android/tv/ui/SelectInputView.java b/src/com/android/tv/ui/SelectInputView.java
index 5e25ae4..dc92111 100644
--- a/src/com/android/tv/ui/SelectInputView.java
+++ b/src/com/android/tv/ui/SelectInputView.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.hardware.hdmi.HdmiDeviceInfo;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
 import android.media.tv.TvInputManager.TvInputCallback;
@@ -37,14 +36,13 @@
 import com.android.tv.ApplicationSingletons;
 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.Tracker;
 import com.android.tv.data.Channel;
 import com.android.tv.util.TvInputManagerHelper;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -58,7 +56,7 @@
 
     private final TvInputManagerHelper mTvInputManagerHelper;
     private final List<TvInputInfo> mInputList = new ArrayList<>();
-    private final InputsComparator mComparator = new InputsComparator();
+    private final TvInputManagerHelper.HardwareInputComparator mComparator;
     private final Tracker mTracker;
     private final DurationTimer mViewDurationTimer = new DurationTimer();
     private final TvInputCallback mTvInputCallback = new TvInputCallback() {
@@ -149,6 +147,8 @@
         ApplicationSingletons appSingletons = TvApplication.getSingletons(context);
         mTracker = appSingletons.getTracker();
         mTvInputManagerHelper = appSingletons.getTvInputManagerHelper();
+        mComparator =
+                new TvInputManagerHelper.HardwareInputComparator(context, mTvInputManagerHelper);
 
         Resources resources = context.getResources();
         mInputItemHeight = resources.getDimensionPixelSize(R.dimen.input_banner_item_height);
@@ -385,72 +385,6 @@
         }
     }
 
-    private class InputsComparator implements Comparator<TvInputInfo> {
-        @Override
-        public int compare(TvInputInfo lhs, TvInputInfo rhs) {
-            if (lhs == null) {
-                return (rhs == null) ? 0 : 1;
-            }
-            if (rhs == null) {
-                return -1;
-            }
-
-            boolean enabledL = isInputEnabled(lhs);
-            boolean enabledR = isInputEnabled(rhs);
-            if (enabledL != enabledR) {
-                return enabledL ? -1 : 1;
-            }
-
-            int priorityL = getPriority(lhs);
-            int priorityR = getPriority(rhs);
-            if (priorityL != priorityR) {
-                return priorityR - priorityL;
-            }
-
-            String customLabelL = (String) lhs.loadCustomLabel(getContext());
-            String customLabelR = (String) rhs.loadCustomLabel(getContext());
-            if (!TextUtils.equals(customLabelL, customLabelR)) {
-                customLabelL = customLabelL == null ? "" : customLabelL;
-                customLabelR = customLabelR == null ? "" : customLabelR;
-                return customLabelL.compareToIgnoreCase(customLabelR);
-            }
-
-            String labelL = (String) lhs.loadLabel(getContext());
-            String labelR = (String) rhs.loadLabel(getContext());
-            labelL = labelL == null ? "" : labelL;
-            labelR = labelR == null ? "" : labelR;
-            return labelL.compareToIgnoreCase(labelR);
-        }
-
-        private int getPriority(TvInputInfo info) {
-            switch (info.getType()) {
-                case TvInputInfo.TYPE_TUNER:
-                    return 9;
-                case TvInputInfo.TYPE_HDMI:
-                    HdmiDeviceInfo hdmiInfo = info.getHdmiDeviceInfo();
-                    if (hdmiInfo != null && hdmiInfo.isCecDevice()) {
-                        return 8;
-                    }
-                    return 7;
-                case TvInputInfo.TYPE_DVI:
-                    return 6;
-                case TvInputInfo.TYPE_COMPONENT:
-                    return 5;
-                case TvInputInfo.TYPE_SVIDEO:
-                    return 4;
-                case TvInputInfo.TYPE_COMPOSITE:
-                    return 3;
-                case TvInputInfo.TYPE_DISPLAY_PORT:
-                    return 2;
-                case TvInputInfo.TYPE_VGA:
-                    return 1;
-                case TvInputInfo.TYPE_SCART:
-                default:
-                    return 0;
-            }
-        }
-    }
-
     /**
      * A callback interface for the input selection.
      */
diff --git a/src/com/android/tv/ui/TunableTvView.java b/src/com/android/tv/ui/TunableTvView.java
index cbe459f..4838669 100644
--- a/src/com/android/tv/ui/TunableTvView.java
+++ b/src/com/android/tv/ui/TunableTvView.java
@@ -19,9 +19,18 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.TimeInterpolator;
-import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ApplicationErrorReport;
 import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.media.PlaybackParams;
 import android.media.tv.TvContentRating;
 import android.media.tv.TvInputInfo;
@@ -33,12 +42,11 @@
 import android.net.ConnectivityManager;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.annotation.UiThread;
-import android.support.v4.os.BuildCompat;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
@@ -47,23 +55,29 @@
 import android.view.MotionEvent;
 import android.view.SurfaceView;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
 
 import com.android.tv.ApplicationSingletons;
+import com.android.tv.Features;
 import com.android.tv.InputSessionManager;
 import com.android.tv.InputSessionManager.TvViewSession;
 import com.android.tv.R;
 import com.android.tv.TvApplication;
-import com.android.tv.analytics.DurationTimer;
+import com.android.tv.data.Program;
+import com.android.tv.data.ProgramDataManager;
+import com.android.tv.parental.ParentalControlSettings;
+import com.android.tv.util.DurationTimer;
+import com.android.tv.util.Debug;
 import com.android.tv.analytics.Tracker;
+import com.android.tv.common.BuildConfig;
 import com.android.tv.common.feature.CommonFeatures;
 import com.android.tv.data.Channel;
 import com.android.tv.data.StreamInfo;
 import com.android.tv.data.WatchedHistoryManager;
 import com.android.tv.parental.ContentRatingsManager;
 import com.android.tv.recommendation.NotificationService;
+import com.android.tv.util.ImageLoader;
 import com.android.tv.util.NetworkUtils;
 import com.android.tv.util.PermissionUtils;
 import com.android.tv.util.TvInputManagerHelper;
@@ -79,6 +93,8 @@
 
     public static final int VIDEO_UNAVAILABLE_REASON_NOT_TUNED = -1;
     public static final int VIDEO_UNAVAILABLE_REASON_NO_RESOURCE = -2;
+    public static final int VIDEO_UNAVAILABLE_REASON_SCREEN_BLOCKED = -3;
+    public static final int VIDEO_UNAVAILABLE_REASON_NONE = -100;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({BLOCK_SCREEN_TYPE_NO_UI, BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW, BLOCK_SCREEN_TYPE_NORMAL})
@@ -105,17 +121,17 @@
     private static final int FADING_IN = 2;
     private static final int FADING_OUT = 3;
 
-    // It is too small to see the description text without PIP_BLOCK_SCREEN_SCALE_FACTOR.
-    private static final float PIP_BLOCK_SCREEN_SCALE_FACTOR = 1.2f;
-
     private AppLayerTvView mTvView;
     private TvViewSession mTvViewSession;
     private Channel mCurrentChannel;
     private TvInputManagerHelper mInputManagerHelper;
     private ContentRatingsManager mContentRatingsManager;
+    private ParentalControlSettings mParentalControlSettings;
+    private ProgramDataManager mProgramDataManager;
     @Nullable
     private WatchedHistoryManager mWatchedHistoryManager;
     private boolean mStarted;
+    private String mTagetInputId;
     private TvInputInfo mInputInfo;
     private OnTuneListener mOnTuneListener;
     private int mVideoWidth;
@@ -125,7 +141,6 @@
     private float mVideoDisplayAspectRatio;
     private int mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
     private boolean mHasClosedCaption = false;
-    private boolean mVideoAvailable;
     private boolean mScreenBlocked;
     private OnScreenBlockingChangedListener mOnScreenBlockedListener;
     private TvContentRating mBlockedContentRating;
@@ -136,10 +151,8 @@
     private boolean mParentControlEnabled;
     private int mFixedSurfaceWidth;
     private int mFixedSurfaceHeight;
-    private boolean mIsPip;
-    private int mScreenHeight;
-    private int mShrunkenTvViewHeight;
     private final boolean mCanModifyParentalControls;
+    private boolean mIsUnderShrunken;
 
     @TimeShiftState private int mTimeShiftState = TIME_SHIFT_STATE_NONE;
     private TimeShiftListener mTimeShiftListener;
@@ -150,21 +163,16 @@
     private final DurationTimer mChannelViewTimer = new DurationTimer();
     private InternetCheckTask mInternetCheckTask;
 
-    // A block screen view which has lock icon with black background.
-    // This indicates that user's action is needed to play video.
+    // A block screen view to hide the real TV view underlying. It may be used to enforce parental
+    // control, or hide screen when there's no video available and show appropriate information.
     private final BlockScreenView mBlockScreenView;
-
-    // A View to hide screen when there's problem in video playback.
-    private final BlockScreenView mHideScreenView;
-
-    // A View to block screen until onContentAllowed is received if parental control is on.
-    private final View mBlockScreenForTuneView;
+    private final int mTuningImageColorFilter;
 
     // A spinner view to show buffering status.
     private final View mBufferingSpinnerView;
 
-    // A View for fade-in/out animation
     private final View mDimScreenView;
+
     private int mFadeState = FADED_IN;
     private Runnable mActionAfterFade;
 
@@ -286,21 +294,77 @@
 
         @Override
         public void onVideoAvailable(String inputId) {
-            unhideScreenByVideoAvailability();
+            if (DEBUG) Log.d(TAG, "onVideoAvailable: {inputId=" + inputId + "}");
+            Debug.getTimer(Debug.TAG_START_UP_TIMER).log("Start up of Live TV ends," +
+                    " TunableTvView.onVideoAvailable resets timer");
+            long startUpDurationTime = Debug.getTimer(Debug.TAG_START_UP_TIMER).reset();
+            Debug.removeTimer(Debug.TAG_START_UP_TIMER);
+            if (BuildConfig.ENG && startUpDurationTime > Debug.TIME_START_UP_DURATION_THRESHOLD) {
+                showAlertDialogForLongStartUp();
+            }
+            mVideoUnavailableReason = VIDEO_UNAVAILABLE_REASON_NONE;
+            updateBlockScreenAndMuting();
             if (mOnTuneListener != null) {
                 mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
             }
         }
 
+        private void showAlertDialogForLongStartUp() {
+            new AlertDialog.Builder(getContext()).setTitle(
+                    getContext().getString(R.string.settings_send_feedback))
+                    .setMessage("Because the start up time of Live channels is too long," +
+                            " please send feedback")
+                    .setPositiveButton(android.R.string.ok,
+                            new DialogInterface.OnClickListener() {
+                                @Override
+                                public void onClick(DialogInterface dialogInterface, int i) {
+                                    Intent intent = new Intent(Intent.ACTION_APP_ERROR);
+                                    ApplicationErrorReport report = new ApplicationErrorReport();
+                                    report.packageName = report.processName = getContext()
+                                            .getApplicationContext().getPackageName();
+                                    report.time = System.currentTimeMillis();
+                                    report.type = ApplicationErrorReport.TYPE_CRASH;
+
+                                    // Add the crash info to add title of feedback automatically.
+                                    ApplicationErrorReport.CrashInfo crash = new
+                                            ApplicationErrorReport.CrashInfo();
+                                    crash.exceptionClassName =
+                                            "Live TV start up takes long time";
+                                    crash.exceptionMessage =
+                                            "The start up time of Live TV is too long";
+                                    report.crashInfo = crash;
+
+                                    intent.putExtra(Intent.EXTRA_BUG_REPORT, report);
+                                    getContext().startActivity(intent);
+                                }
+                            })
+                    .setNegativeButton(android.R.string.no, null)
+                    .show();
+        }
+
         @Override
         public void onVideoUnavailable(String inputId, int reason) {
-            hideScreenByVideoAvailability(inputId, reason);
+            if (reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING
+                    && reason != TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING) {
+                Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+                        "TunableTvView.onVideoUnAvailable reason = (" + reason
+                                + ") and removes timer");
+                Debug.removeTimer(Debug.TAG_START_UP_TIMER);
+            } else {
+                Debug.getTimer(Debug.TAG_START_UP_TIMER).log(
+                        "TunableTvView.onVideoUnAvailable reason = (" + reason + ")");
+            }
+            mVideoUnavailableReason = reason;
+            if (closePipIfNeeded()) {
+                return;
+            }
+            updateBlockScreenAndMuting();
             if (mOnTuneListener != null) {
                 mOnTuneListener.onStreamInfoChanged(TunableTvView.this);
             }
             switch (reason) {
-                case TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING:
                 case TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN:
+                case TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING:
                 case TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL:
                     mTracker.sendChannelVideoUnavailable(mCurrentChannel, reason);
                 default:
@@ -310,8 +374,8 @@
 
         @Override
         public void onContentAllowed(String inputId) {
-            mBlockScreenForTuneView.setVisibility(View.GONE);
-            unblockScreenByContentRating();
+            mBlockedContentRating = null;
+            updateBlockScreenAndMuting();
             if (mOnTuneListener != null) {
                 mOnTuneListener.onContentAllowed();
             }
@@ -319,7 +383,14 @@
 
         @Override
         public void onContentBlocked(String inputId, TvContentRating rating) {
-            blockScreenByContentRating(rating);
+            if (rating != null && rating.equals(mBlockedContentRating)) {
+                return;
+            }
+            mBlockedContentRating = rating;
+            if (closePipIfNeeded()) {
+                return;
+            }
+            updateBlockScreenAndMuting();
             if (mOnTuneListener != null) {
                 mOnTuneListener.onContentBlocked();
             }
@@ -327,6 +398,10 @@
 
         @Override
         public void onTimeShiftStatusChanged(String inputId, int status) {
+            if (DEBUG) {
+                Log.d(TAG, "onTimeShiftStatusChanged: {inputId=" + inputId + ", status=" + status +
+                        "}");
+            }
             boolean available = status == TvInputManager.TIME_SHIFT_STATUS_AVAILABLE;
             setTimeShiftAvailable(available);
         }
@@ -361,25 +436,17 @@
         mTracker = appSingletons.getTracker();
         mBlockScreenType = BLOCK_SCREEN_TYPE_NORMAL;
         mBlockScreenView = (BlockScreenView) findViewById(R.id.block_screen);
-        if (!mCanModifyParentalControls) {
-            mBlockScreenView.setImage(R.drawable.ic_message_lock_no_permission);
-            mBlockScreenView.setScaleType(ImageView.ScaleType.CENTER);
-        } else {
-            mBlockScreenView.setImage(R.drawable.ic_message_lock);
-        }
-        mBlockScreenView.setShrunkenImage(R.drawable.ic_message_lock_preview);
-        mBlockScreenView.addFadeOutAnimationListener(new AnimatorListenerAdapter() {
+        mBlockScreenView.addInfoFadeInAnimationListener(new AnimatorListenerAdapter() {
             @Override
-            public void onAnimationEnd(Animator animation) {
+            public void onAnimationStart(Animator animation) {
                 adjustBlockScreenSpacingAndText();
             }
         });
 
-        mHideScreenView = (BlockScreenView) findViewById(R.id.hide_screen);
-        mHideScreenView.setImageVisibility(false);
         mBufferingSpinnerView = findViewById(R.id.buffering_spinner);
-        mBlockScreenForTuneView = findViewById(R.id.block_screen_for_tune);
-        mDimScreenView = findViewById(R.id.dim);
+        mTuningImageColorFilter = getResources()
+                .getColor(R.color.tvview_block_image_color_filter, null);
+        mDimScreenView = findViewById(R.id.dim_screen);
         mDimScreenView.animate().setListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
@@ -397,27 +464,21 @@
         });
     }
 
-    public void initialize(AppLayerTvView tvView, boolean isPip, int screenHeight,
-            int shrunkenTvViewHeight) {
-        mTvView = tvView;
+    public void initialize(ProgramDataManager programDataManager,
+            TvInputManagerHelper tvInputManagerHelper) {
+        mTvView = (AppLayerTvView) findViewById(R.id.tv_view);
+        mProgramDataManager = programDataManager;
+        mInputManagerHelper = tvInputManagerHelper;
+        mContentRatingsManager = tvInputManagerHelper.getContentRatingsManager();
+        mParentalControlSettings = tvInputManagerHelper.getParentalControlSettings();
         if (mInputSessionManager != null) {
-            mTvViewSession = mInputSessionManager.createTvViewSession(tvView, this, mCallback);
+            mTvViewSession = mInputSessionManager.createTvViewSession(mTvView, this, mCallback);
         } else {
             mTvView.setCallback(mCallback);
         }
-        mIsPip = isPip;
-        mScreenHeight = screenHeight;
-        mShrunkenTvViewHeight = shrunkenTvViewHeight;
-        mTvView.setZOrderOnTop(isPip);
-        copyLayoutParamsToTvView();
     }
 
-    public void start(TvInputManagerHelper tvInputManagerHelper) {
-        mInputManagerHelper = tvInputManagerHelper;
-        mContentRatingsManager = tvInputManagerHelper.getContentRatingsManager();
-        if (mStarted) {
-            return;
-        }
+    public void start() {
         mStarted = true;
     }
 
@@ -431,7 +492,8 @@
             } else {
                 mTvView.tune(inputId, channelUri);
             }
-            hideScreenByVideoAvailability(inputId, TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
+            mVideoUnavailableReason = TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING;
+            updateBlockScreenAndMuting();
         }
     }
 
@@ -462,15 +524,16 @@
     }
 
     /**
-     * Reset TV view.
+     * Resets TV view.
      */
     public void reset() {
         resetInternal();
-        hideScreenByVideoAvailability(null, VIDEO_UNAVAILABLE_REASON_NOT_TUNED);
+        mVideoUnavailableReason = VIDEO_UNAVAILABLE_REASON_NOT_TUNED;
+        updateBlockScreenAndMuting();
     }
 
     /**
-     * Reset TV view to acquire the recording session.
+     * Resets TV view to acquire the recording session.
      */
     public void resetByRecording() {
         resetInternal();
@@ -497,6 +560,13 @@
         mWatchedHistoryManager = watchedHistoryManager;
     }
 
+    /**
+     * Sets if the TunableTvView is under shrunken.
+     */
+    public void setIsUnderShrunken(boolean isUnderShrunken) {
+        mIsUnderShrunken = isUnderShrunken;
+    }
+
     public boolean isPlaying() {
         return mStarted;
     }
@@ -506,8 +576,9 @@
      */
     public void onParentalControlChanged(boolean enabled) {
         mParentControlEnabled = enabled;
-        if (!mParentControlEnabled) {
-            mBlockScreenForTuneView.setVisibility(View.GONE);
+        if (!enabled) {
+            // Unblock screen immediately if parental control is turned off
+            updateBlockScreenAndMuting();
         }
     }
 
@@ -519,6 +590,7 @@
      *         if the state is disconnected or channelId doesn't exist, it returns false.
      */
     public boolean tuneTo(Channel channel, Bundle params, OnTuneListener listener) {
+        Debug.getTimer(Debug.TAG_START_UP_TIMER).log("TunableTvView.tuneTo");
         if (!mStarted) {
             throw new IllegalStateException("TvView isn't started");
         }
@@ -541,6 +613,7 @@
                 && params.getString(NotificationService.TUNE_PARAMS_RECOMMENDATION_TYPE) != null;
         boolean needSurfaceSizeUpdate = false;
         if (!inputInfo.equals(mInputInfo)) {
+            mTagetInputId = inputInfo.getId();
             mInputInfo = inputInfo;
             mCanReceiveInputEvent = getContext().getPackageManager().checkPermission(
                     PERMISSION_RECEIVE_INPUT_EVENT, mInputInfo.getServiceInfo().packageName)
@@ -560,6 +633,7 @@
         mVideoDisplayAspectRatio = 0f;
         mAudioChannelCount = StreamInfo.AUDIO_CHANNEL_COUNT_UNKNOWN;
         mHasClosedCaption = false;
+        mBlockedContentRating = null;
         mTimeShiftCurrentPositionMs = TvInputManager.TIME_SHIFT_INVALID_TIME;
         // To reduce the IPCs, unregister the callback here and register it when necessary.
         mTvView.setTimeShiftPositionCallback(null);
@@ -569,19 +643,13 @@
             // So we need to call SurfaceHolder.setFixedSize for the new SurfaceView.
             getSurfaceView().getHolder().setFixedSize(mFixedSurfaceWidth, mFixedSurfaceHeight);
         }
-        hideScreenByVideoAvailability(mInputInfo.getId(),
-                TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING);
+        mVideoUnavailableReason = TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING;
         if (mTvViewSession != null) {
             mTvViewSession.tune(channel, params, listener);
         } else {
             mTvView.tune(mInputInfo.getId(), mCurrentChannel.getUri(), params);
         }
-        unblockScreenByContentRating();
-        if (channel.isPassthrough()) {
-            mBlockScreenForTuneView.setVisibility(View.GONE);
-        } else if (mParentControlEnabled) {
-            mBlockScreenForTuneView.setVisibility(View.VISIBLE);
-        }
+        updateBlockScreenAndMuting();
         if (mOnTuneListener != null) {
             mOnTuneListener.onStreamInfoChanged(this);
         }
@@ -711,7 +779,13 @@
 
     @Override
     public boolean isVideoAvailable() {
-        return mVideoAvailable;
+        return mVideoUnavailableReason == VIDEO_UNAVAILABLE_REASON_NONE;
+    }
+
+    @Override
+    public boolean isVideoOrAudioAvailable() {
+        return mVideoUnavailableReason == VIDEO_UNAVAILABLE_REASON_NONE
+                || mVideoUnavailableReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY;
     }
 
     @Override
@@ -747,12 +821,50 @@
     }
 
     /**
-     * Returns if the screen is blocked by {@link #blockScreen()}.
+     * Gets {@link android.view.ViewGroup.MarginLayoutParams} of the underlying
+     * {@link TvView}, which is the actual view to play live TV videos.
+     */
+    public MarginLayoutParams getTvViewLayoutParams() {
+        return (MarginLayoutParams) mTvView.getLayoutParams();
+    }
+
+    /**
+     * Sets {@link android.view.ViewGroup.MarginLayoutParams} of the underlying
+     * {@link TvView}, which is the actual view to play live TV videos.
+     */
+    public void setTvViewLayoutParams(MarginLayoutParams layoutParams) {
+        mTvView.setLayoutParams(layoutParams);
+    }
+
+    /**
+     * Gets the underlying {@link AppLayerTvView}, which is the actual view to play live TV videos.
+     */
+    public TvView getTvView() {
+        return mTvView;
+    }
+
+    /**
+     * Returns if the screen is blocked, either by {@link #blockOrUnblockScreen(boolean)} or because
+     * the content is blocked.
+     */
+    public boolean isBlocked() {
+        return isScreenBlocked() || isContentBlocked();
+    }
+
+    /**
+     * Returns if the screen is blocked by {@link #blockOrUnblockScreen(boolean)}.
      */
     public boolean isScreenBlocked() {
         return mScreenBlocked;
     }
 
+    /**
+     * Returns {@code true} if the content is blocked, otherwise {@code false}.
+     */
+    public boolean isContentBlocked() {
+        return mBlockedContentRating != null;
+    }
+
     public void setOnScreenBlockedListener(OnScreenBlockingChangedListener listener) {
         mOnScreenBlockedListener = listener;
     }
@@ -766,77 +878,23 @@
     }
 
     /**
-     * Locks current TV screen and mutes.
+     * Blocks/unblocks current TV screen and mutes.
      * There would be black screen with lock icon in order to show that
      * screen block is intended and not an error.
-     * TODO: Accept parameter to show lock icon or not.
+     *
+     * @param blockOrUnblock {@code true} to block the screen, or {@code false} to unblock.
      */
-    public void blockScreen() {
-        mScreenBlocked = true;
-        checkBlockScreenAndMuteNeeded();
+    public void blockOrUnblockScreen(boolean blockOrUnblock) {
+        if (mScreenBlocked == blockOrUnblock) {
+            return;
+        }
+        mScreenBlocked = blockOrUnblock;
+        if (closePipIfNeeded()) {
+            return;
+        }
+        updateBlockScreenAndMuting();
         if (mOnScreenBlockedListener != null) {
-            mOnScreenBlockedListener.onScreenBlockingChanged(true);
-        }
-    }
-
-    private void blockScreenByContentRating(TvContentRating rating) {
-        mBlockedContentRating = rating;
-        checkBlockScreenAndMuteNeeded();
-    }
-
-    @Override
-    @SuppressLint("RtlHardcoded")
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        if (mIsPip) {
-            int height = bottom - top;
-            float scale;
-            if (mBlockScreenType == BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW) {
-                scale = height * PIP_BLOCK_SCREEN_SCALE_FACTOR / mShrunkenTvViewHeight;
-            } else {
-                scale = height * PIP_BLOCK_SCREEN_SCALE_FACTOR / mScreenHeight;
-            }
-            // TODO: need to get UX confirmation.
-            mBlockScreenView.scaleContainerView(scale);
-        }
-    }
-
-    @Override
-    public void setLayoutParams(ViewGroup.LayoutParams params) {
-        super.setLayoutParams(params);
-        if (mTvView != null) {
-            copyLayoutParamsToTvView();
-        }
-    }
-
-    private void copyLayoutParamsToTvView() {
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
-        FrameLayout.LayoutParams tvViewLp = (FrameLayout.LayoutParams) mTvView.getLayoutParams();
-        if (tvViewLp.bottomMargin != lp.bottomMargin
-                || tvViewLp.topMargin != lp.topMargin
-                || tvViewLp.leftMargin != lp.leftMargin
-                || tvViewLp.rightMargin != lp.rightMargin
-                || tvViewLp.gravity != lp.gravity
-                || tvViewLp.height != lp.height
-                || tvViewLp.width != lp.width) {
-            if (lp.topMargin == tvViewLp.topMargin && lp.leftMargin == tvViewLp.leftMargin
-                    && !BuildCompat.isAtLeastN()) {
-                // HACK: If top and left position aren't changed and SurfaceHolder.setFixedSize is
-                // used, SurfaceView doesn't catch the width and height change. It causes a bug that
-                // PIP size change isn't shown when PIP is located TOP|LEFT. So we adjust 1 px for
-                // small size PIP as a workaround.
-                // Note: This framework issue has been fixed from NYC.
-                tvViewLp.leftMargin = lp.leftMargin + 1;
-            } else {
-                tvViewLp.leftMargin = lp.leftMargin;
-            }
-            tvViewLp.topMargin = lp.topMargin;
-            tvViewLp.bottomMargin = lp.bottomMargin;
-            tvViewLp.rightMargin = lp.rightMargin;
-            tvViewLp.gravity = lp.gravity;
-            tvViewLp.height = lp.height;
-            tvViewLp.width = lp.width;
-            mTvView.setLayoutParams(tvViewLp);
+            mOnScreenBlockedListener.onScreenBlockingChanged(blockOrUnblock);
         }
     }
 
@@ -859,35 +917,67 @@
      * @param type The type of block screen to set.
      */
     public void setBlockScreenType(@BlockScreenType int type) {
-        // TODO: need to support the transition from NORMAL to SHRUNKEN and vice verse.
         if (mBlockScreenType != type) {
             mBlockScreenType = type;
-            updateBlockScreenUI(true);
+            updateBlockScreen(true);
         }
     }
 
-    private void updateBlockScreenUI(boolean animation) {
+    private void updateBlockScreen(boolean animation) {
         mBlockScreenView.endAnimations();
-
-        if (!mScreenBlocked && mBlockedContentRating == null) {
-            mBlockScreenView.setVisibility(GONE);
-            return;
+        int blockReason = (mScreenBlocked || mBlockedContentRating != null)
+                && mParentControlEnabled ? VIDEO_UNAVAILABLE_REASON_SCREEN_BLOCKED
+                        : mVideoUnavailableReason;
+        if (blockReason != VIDEO_UNAVAILABLE_REASON_NONE) {
+            mBufferingSpinnerView.setVisibility(
+                    blockReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING
+                            || blockReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING ?
+                            VISIBLE : GONE);
+            if (!animation) {
+                adjustBlockScreenSpacingAndText();
+            }
+            if (blockReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING) {
+                return;
+            }
+            mBlockScreenView.setVisibility(VISIBLE);
+            mBlockScreenView.setBackgroundImage(null);
+            if (blockReason == VIDEO_UNAVAILABLE_REASON_SCREEN_BLOCKED) {
+                mBlockScreenView.setIconVisibility(true);
+                if (!mCanModifyParentalControls) {
+                    mBlockScreenView.setIconImage(R.drawable.ic_message_lock_no_permission);
+                    mBlockScreenView.setIconScaleType(ImageView.ScaleType.CENTER);
+                } else {
+                    mBlockScreenView.setIconImage(R.drawable.ic_message_lock);
+                    mBlockScreenView.setIconScaleType(ImageView.ScaleType.FIT_CENTER);
+                }
+            } else {
+                if (mInternetCheckTask != null) {
+                    mInternetCheckTask.cancel(true);
+                    mInternetCheckTask = null;
+                }
+                mBlockScreenView.setIconVisibility(false);
+                if (blockReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING) {
+                    showImageForTuningIfNeeded();
+                } else if (blockReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN
+                        && mCurrentChannel != null && !mCurrentChannel.isPhysicalTunerChannel()) {
+                    mInternetCheckTask = new InternetCheckTask();
+                    mInternetCheckTask.execute();
+                }
+            }
+            mBlockScreenView.onBlockStatusChanged(mBlockScreenType, animation);
+        } else {
+            mBufferingSpinnerView.setVisibility(GONE);
+            if (mBlockScreenView.getVisibility() == VISIBLE) {
+                mBlockScreenView.fadeOut();
+            }
         }
-
-        mBlockScreenView.setVisibility(VISIBLE);
-        if (!animation || mBlockScreenType != TunableTvView.BLOCK_SCREEN_TYPE_NO_UI) {
-            adjustBlockScreenSpacingAndText();
-        }
-        mBlockScreenView.onBlockStatusChanged(mBlockScreenType, animation);
     }
 
     private void adjustBlockScreenSpacingAndText() {
-        // TODO: need to add animation for padding change when the block screen type is changed
-        // NORMAL to SHRUNKEN and vice verse.
         mBlockScreenView.setSpacing(mBlockScreenType);
         String text = getBlockScreenText();
         if (text != null) {
-            mBlockScreenView.setText(text);
+            mBlockScreenView.setInfoText(text);
         }
     }
 
@@ -896,151 +986,121 @@
      * Note that returning {@code null} value means that the current text should not be changed.
      */
     private String getBlockScreenText() {
-        if (mScreenBlocked) {
+        // TODO: add a test for this method
+        Resources res = getResources();
+        if (mScreenBlocked && mParentControlEnabled) {
             switch (mBlockScreenType) {
                 case BLOCK_SCREEN_TYPE_NO_UI:
                 case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
                     return "";
                 case BLOCK_SCREEN_TYPE_NORMAL:
                     if (mCanModifyParentalControls) {
-                        return getResources().getString(R.string.tvview_channel_locked);
+                        return res.getString(R.string.tvview_channel_locked);
                     } else {
-                        return getResources().getString(
-                                R.string.tvview_channel_locked_no_permission);
+                        return res.getString(R.string.tvview_channel_locked_no_permission);
                     }
             }
-        } else if (mBlockedContentRating != null) {
+        } else if (mBlockedContentRating != null && mParentControlEnabled) {
             String name = mContentRatingsManager.getDisplayNameForRating(mBlockedContentRating);
             switch (mBlockScreenType) {
                 case BLOCK_SCREEN_TYPE_NO_UI:
                     return "";
                 case BLOCK_SCREEN_TYPE_SHRUNKEN_TV_VIEW:
                     if (TextUtils.isEmpty(name)) {
-                        return getResources().getString(R.string.shrunken_tvview_content_locked);
+                        return res.getString(R.string.shrunken_tvview_content_locked);
+                    } else if (name.equals(res.getString(R.string.unrated_rating_name))) {
+                        return res.getString(R.string.shrunken_tvview_content_locked_unrated);
                     } else {
-                        return getContext().getString(
-                                R.string.shrunken_tvview_content_locked_format, name);
+                        return res.getString(R.string.shrunken_tvview_content_locked_format, name);
                     }
                 case BLOCK_SCREEN_TYPE_NORMAL:
                     if (TextUtils.isEmpty(name)) {
                         if (mCanModifyParentalControls) {
-                            return getResources().getString(R.string.tvview_content_locked);
+                            return res.getString(R.string.tvview_content_locked);
                         } else {
-                            return getResources().getString(
-                                    R.string.tvview_content_locked_no_permission);
+                            return res.getString(R.string.tvview_content_locked_no_permission);
                         }
                     } else {
                         if (mCanModifyParentalControls) {
-                            return getContext().getString(
-                                    R.string.tvview_content_locked_format, name);
+                            return name.equals(res.getString(R.string.unrated_rating_name))
+                                    ? res.getString(R.string.tvview_content_locked_unrated)
+                                    : res.getString(R.string.tvview_content_locked_format, name);
                         } else {
-                            return getContext().getString(
-                                    R.string.tvview_content_locked_format_no_permission, name);
+                            return name.equals(res.getString(R.string.unrated_rating_name))
+                                    ? res.getString(
+                                            R.string.tvview_content_locked_unrated_no_permission)
+                                    : res.getString(
+                                            R.string.tvview_content_locked_format_no_permission,
+                                            name);
                         }
                     }
             }
+        } else if (mVideoUnavailableReason != VIDEO_UNAVAILABLE_REASON_NONE) {
+            switch (mVideoUnavailableReason) {
+                case TvInputManager.VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY:
+                    return res.getString(R.string.tvview_msg_audio_only);
+                case TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL:
+                    return res.getString(R.string.tvview_msg_weak_signal);
+                case VIDEO_UNAVAILABLE_REASON_NO_RESOURCE:
+                    return getTuneConflictMessage();
+                default:
+                    return "";
+            }
         }
         return null;
     }
 
-    private void checkBlockScreenAndMuteNeeded() {
-        updateBlockScreenUI(false);
-        if (mScreenBlocked || mBlockedContentRating != null) {
-            mute();
-            if (mIsPip) {
-                // If we don't make mTvView invisible, some frames are leaked when a user changes
-                // PIP layout in options.
-                // Note: When video is unavailable, we keep the mTvView's visibility, because
-                // TIS implementation may not send video available with no surface.
-                mTvView.setVisibility(View.INVISIBLE);
+    private boolean closePipIfNeeded() {
+        if (Features.PICTURE_IN_PICTURE.isEnabled(getContext())
+                && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+                && ((Activity) getContext()).isInPictureInPictureMode()
+                && (mScreenBlocked
+                        || mBlockedContentRating != null
+                        || mVideoUnavailableReason
+                                == TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN)) {
+            ((Activity) getContext()).finish();
+            return true;
+        }
+        return false;
+    }
+
+    private void updateBlockScreenAndMuting() {
+        updateBlockScreen(false);
+        updateMuteStatus();
+    }
+
+    private boolean shouldShowImageForTuning() {
+        if (mVideoUnavailableReason != TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING
+                || mScreenBlocked || mBlockedContentRating != null || mCurrentChannel == null
+                || mIsUnderShrunken || getWidth() == 0 || getWidth() == 0 || !isBundledInput()) {
+            return false;
+        }
+        Program currentProgram = mProgramDataManager.getCurrentProgram(mCurrentChannel.getId());
+        if (currentProgram == null) {
+            return false;
+        }
+        TvContentRating rating =
+                mParentalControlSettings.getBlockedRating(currentProgram.getContentRatings());
+        return !(mParentControlEnabled && rating != null);
+    }
+
+    private void showImageForTuningIfNeeded() {
+        if (shouldShowImageForTuning()) {
+            if (mCurrentChannel == null) {
+                return;
             }
-        } else {
-            unmuteIfPossible();
-            if (mIsPip) {
-                mTvView.setVisibility(View.VISIBLE);
+            Program currentProgram = mProgramDataManager.getCurrentProgram(mCurrentChannel.getId());
+            if (currentProgram != null) {
+                currentProgram.loadPosterArt(getContext(), getWidth(), getHeight(),
+                        createProgramPosterArtCallback(mCurrentChannel.getId()));
             }
         }
     }
 
-    public void unblockScreen() {
-        mScreenBlocked = false;
-        checkBlockScreenAndMuteNeeded();
-        if (mOnScreenBlockedListener != null) {
-            mOnScreenBlockedListener.onScreenBlockingChanged(false);
-        }
-    }
-
-    private void unblockScreenByContentRating() {
-        mBlockedContentRating = null;
-        checkBlockScreenAndMuteNeeded();
-    }
-
-    @UiThread
-    private void hideScreenByVideoAvailability(String inputId, int reason) {
-        mVideoAvailable = false;
-        mVideoUnavailableReason = reason;
-        if (mInternetCheckTask != null) {
-            mInternetCheckTask.cancel(true);
-            mInternetCheckTask = null;
-        }
-        switch (reason) {
-            case TvInputManager.VIDEO_UNAVAILABLE_REASON_AUDIO_ONLY:
-                mHideScreenView.setVisibility(VISIBLE);
-                mHideScreenView.setImageVisibility(false);
-                mHideScreenView.setText(R.string.tvview_msg_audio_only);
-                mBufferingSpinnerView.setVisibility(GONE);
-                unmuteIfPossible();
-                break;
-            case TvInputManager.VIDEO_UNAVAILABLE_REASON_BUFFERING:
-                mBufferingSpinnerView.setVisibility(VISIBLE);
-                mute();
-                break;
-            case TvInputManager.VIDEO_UNAVAILABLE_REASON_WEAK_SIGNAL:
-                mHideScreenView.setVisibility(VISIBLE);
-                mHideScreenView.setText(R.string.tvview_msg_weak_signal);
-                mBufferingSpinnerView.setVisibility(GONE);
-                mute();
-                break;
-            case TvInputManager.VIDEO_UNAVAILABLE_REASON_TUNING:
-                mHideScreenView.setVisibility(VISIBLE);
-                mHideScreenView.setImageVisibility(false);
-                mHideScreenView.setText(null);
-                mBufferingSpinnerView.setVisibility(VISIBLE);
-                mute();
-                break;
-            case VIDEO_UNAVAILABLE_REASON_NOT_TUNED:
-                mHideScreenView.setVisibility(VISIBLE);
-                mHideScreenView.setImageVisibility(false);
-                mHideScreenView.setText(null);
-                mBufferingSpinnerView.setVisibility(GONE);
-                mute();
-                break;
-            case VIDEO_UNAVAILABLE_REASON_NO_RESOURCE:
-                mHideScreenView.setVisibility(VISIBLE);
-                mHideScreenView.setImageVisibility(false);
-                mHideScreenView.setText(getTuneConflictMessage(inputId));
-                mBufferingSpinnerView.setVisibility(GONE);
-                mute();
-                break;
-            case TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN:
-            default:
-                mHideScreenView.setVisibility(VISIBLE);
-                mHideScreenView.setImageVisibility(false);
-                mHideScreenView.setText(null);
-                mBufferingSpinnerView.setVisibility(GONE);
-                mute();
-                if (mCurrentChannel != null && !mCurrentChannel.isPhysicalTunerChannel()) {
-                    mInternetCheckTask = new InternetCheckTask();
-                    mInternetCheckTask.execute();
-                }
-                break;
-        }
-    }
-
-    private String getTuneConflictMessage(String inputId) {
-        if (inputId != null) {
-            TvInputInfo input = mInputManager.getTvInputInfo(inputId);
-            Long timeMs = mInputSessionManager.getEarliestRecordingSessionEndTimeMs(inputId);
+    private String getTuneConflictMessage() {
+        if (mTagetInputId != null) {
+            TvInputInfo input = mInputManager.getTvInputInfo(mTagetInputId);
+            Long timeMs = mInputSessionManager.getEarliestRecordingSessionEndTimeMs(mTagetInputId);
             if (timeMs != null) {
                 return getResources().getQuantityString(R.plurals.tvview_msg_input_no_resource,
                         input.getTunerCount(),
@@ -1050,27 +1110,36 @@
         return null;
     }
 
-    private void unhideScreenByVideoAvailability() {
-        mVideoAvailable = true;
-        mHideScreenView.setVisibility(GONE);
-        mBufferingSpinnerView.setVisibility(GONE);
-        unmuteIfPossible();
-    }
-
-    private void unmuteIfPossible() {
-        if (mVideoAvailable && !mScreenBlocked && mBlockedContentRating == null) {
-            unmute();
+    private void updateMuteStatus() {
+        // Workaround: TunerTvInputService uses AC3 pass-through implementation, which disables
+        // audio tracks to enforce the mute request. We don't want to send mute request if we are
+        // not going to block the screen to prevent the video jankiness resulted by disabling audio
+        // track before the playback is started. In other way, we should send unmute request before
+        // the playback is started, because TunerTvInput will remember the muted state and mute
+        // itself right way when the playback is going to be started, which results the initial
+        // jankiness, too.
+        boolean isBundledInput = isBundledInput();
+        if ((isBundledInput || isVideoOrAudioAvailable()) && !mScreenBlocked
+                && mBlockedContentRating == null) {
+            if (mIsMuted) {
+                mIsMuted = false;
+                mTvView.setStreamVolume(mVolume);
+            }
+        } else {
+            if (!mIsMuted) {
+                if ((mInputInfo == null || isBundledInput)
+                        && !mScreenBlocked && mBlockedContentRating == null) {
+                    return;
+                }
+                mIsMuted = true;
+                mTvView.setStreamVolume(0);
+            }
         }
     }
 
-    private void mute() {
-        mIsMuted = true;
-        mTvView.setStreamVolume(0);
-    }
-
-    private void unmute() {
-        mIsMuted = false;
-        mTvView.setStreamVolume(mVolume);
+    private boolean isBundledInput() {
+        return mInputInfo != null && mInputInfo.getType() == TvInputInfo.TYPE_TUNER
+                && Utils.isBundledInput(mInputInfo.getId());
     }
 
     /** Returns true if this view is faded out. */
@@ -1268,6 +1337,24 @@
         return mTimeShiftCurrentPositionMs;
     }
 
+    private ImageLoader.ImageLoaderCallback<BlockScreenView> createProgramPosterArtCallback(
+            final long channelId) {
+        return new ImageLoader.ImageLoaderCallback<BlockScreenView>(mBlockScreenView) {
+            @Override
+            public void onBitmapLoaded(BlockScreenView view, @Nullable Bitmap posterArt) {
+                if (posterArt == null || getCurrentChannel() == null
+                        || channelId != getCurrentChannel().getId()
+                        || !shouldShowImageForTuning()) {
+                    return;
+                }
+                Drawable drawablePosterArt = new BitmapDrawable(view.getResources(), posterArt);
+                drawablePosterArt.mutate().setColorFilter(
+                        mTuningImageColorFilter, PorterDuff.Mode.SRC_OVER);
+                view.setBackgroundImage(drawablePosterArt);
+            }
+        };
+    }
+
     /**
      * Used to receive the time-shift events.
      */
@@ -1304,11 +1391,12 @@
         @Override
         protected void onPostExecute(Boolean networkAvailable) {
             mInternetCheckTask = null;
-            if (!mVideoAvailable && !networkAvailable && isAttachedToWindow()
+            if (!networkAvailable && isAttachedToWindow()
+                    && !mScreenBlocked && mBlockedContentRating == null
                     && mVideoUnavailableReason == TvInputManager.VIDEO_UNAVAILABLE_REASON_UNKNOWN) {
-                mHideScreenView.setImageVisibility(true);
-                mHideScreenView.setImage(R.drawable.ic_sad_cloud);
-                mHideScreenView.setText(R.string.tvview_msg_no_internet_connection);
+                mBlockScreenView.setIconVisibility(true);
+                mBlockScreenView.setIconImage(R.drawable.ic_sad_cloud);
+                mBlockScreenView.setInfoText(R.string.tvview_msg_no_internet_connection);
             }
         }
     }
diff --git a/src/com/android/tv/ui/TvOverlayManager.java b/src/com/android/tv/ui/TvOverlayManager.java
index e14b286..9324742 100644
--- a/src/com/android/tv/ui/TvOverlayManager.java
+++ b/src/com/android/tv/ui/TvOverlayManager.java
@@ -20,6 +20,7 @@
 import android.app.FragmentManager;
 import android.app.FragmentManager.OnBackStackChangedListener;
 import android.content.Intent;
+import android.media.tv.TvContentRating;
 import android.media.tv.TvInputInfo;
 import android.os.Bundle;
 import android.os.Handler;
@@ -39,6 +40,7 @@
 import com.android.tv.R;
 import com.android.tv.TimeShiftManager;
 import com.android.tv.TvApplication;
+import com.android.tv.TvOptionsManager;
 import com.android.tv.analytics.Tracker;
 import com.android.tv.common.WeakHandler;
 import com.android.tv.common.feature.CommonFeatures;
@@ -46,14 +48,16 @@
 import com.android.tv.common.ui.setup.SetupFragment;
 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
 import com.android.tv.data.ChannelDataManager;
+import com.android.tv.dialog.DvrHistoryDialogFragment;
 import com.android.tv.dialog.FullscreenDialogFragment;
+import com.android.tv.dialog.HalfSizedDialogFragment;
 import com.android.tv.dialog.PinDialogFragment;
 import com.android.tv.dialog.RecentlyWatchedDialogFragment;
 import com.android.tv.dialog.SafeDismissDialogFragment;
 import com.android.tv.dvr.DvrDataManager;
-import com.android.tv.dvr.ui.DvrActivity;
-import com.android.tv.dvr.ui.HalfSizedDialogFragment;
+import com.android.tv.dvr.ui.browse.DvrBrowseActivity;
 import com.android.tv.guide.ProgramGuide;
+import com.android.tv.license.LicenseDialogFragment;
 import com.android.tv.menu.Menu;
 import com.android.tv.menu.Menu.MenuShowReason;
 import com.android.tv.menu.MenuRowFactory;
@@ -62,7 +66,6 @@
 import com.android.tv.onboarding.SetupSourcesFragment;
 import com.android.tv.search.ProgramGuideSearchFragment;
 import com.android.tv.ui.TvTransitionManager.SceneType;
-import com.android.tv.ui.sidepanel.SettingsFragment;
 import com.android.tv.ui.sidepanel.SideFragmentManager;
 import com.android.tv.ui.sidepanel.parentalcontrols.RatingsFragment;
 import com.android.tv.util.TvInputManagerHelper;
@@ -157,15 +160,47 @@
     // Used for the padded print of the overlay type.
     private static final int NUM_OVERLAY_TYPES = 9;
 
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW, UPDATE_CHANNEL_BANNER_REASON_TUNE,
+            UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST, UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO,
+            UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK,
+            UPDATE_CHANNEL_BANNER_REASON_UPDATE_STREAM_INFO})
+    private @interface ChannelBannerUpdateReason {}
+    /**
+     * Updates channel banner because the channel banner is forced to show.
+     */
+    public static final int UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW = 1;
+    /**
+     * Updates channel banner because of tuning.
+     */
+    public static final int UPDATE_CHANNEL_BANNER_REASON_TUNE = 2;
+    /**
+     * Updates channel banner because of fast tuning.
+     */
+    public static final int UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST = 3;
+    /**
+     * Updates channel banner because of info updating.
+     */
+    public static final int UPDATE_CHANNEL_BANNER_REASON_UPDATE_INFO = 4;
+    /**
+     * Updates channel banner because the current watched channel is locked or unlocked.
+     */
+    public static final int UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK = 5;
+    /**
+     * Updates channel banner because of stream info updating.
+     */
+    public static final int UPDATE_CHANNEL_BANNER_REASON_UPDATE_STREAM_INFO = 6;
+
     private static final String FRAGMENT_TAG_SETUP_SOURCES = "tag_setup_sources";
     private static final String FRAGMENT_TAG_NEW_SOURCES = "tag_new_sources";
 
     private static final Set<String> AVAILABLE_DIALOG_TAGS = new HashSet<>();
     static {
         AVAILABLE_DIALOG_TAGS.add(RecentlyWatchedDialogFragment.DIALOG_TAG);
+        AVAILABLE_DIALOG_TAGS.add(DvrHistoryDialogFragment.DIALOG_TAG);
         AVAILABLE_DIALOG_TAGS.add(PinDialogFragment.DIALOG_TAG);
         AVAILABLE_DIALOG_TAGS.add(FullscreenDialogFragment.DIALOG_TAG);
-        AVAILABLE_DIALOG_TAGS.add(SettingsFragment.LicenseActionItem.DIALOG_TAG);
+        AVAILABLE_DIALOG_TAGS.add(LicenseDialogFragment.DIALOG_TAG);
         AVAILABLE_DIALOG_TAGS.add(RatingsFragment.AttributionItem.DIALOG_TAG);
         AVAILABLE_DIALOG_TAGS.add(HalfSizedDialogFragment.DIALOG_TAG);
     }
@@ -176,8 +211,10 @@
     private final ChannelDataManager mChannelDataManager;
     private final TvInputManagerHelper mInputManager;
     private final Menu mMenu;
+    private final TunableTvView mTvView;
     private final SideFragmentManager mSideFragmentManager;
     private final ProgramGuide mProgramGuide;
+    private final ChannelBannerView mChannelBannerView;
     private final KeypadChannelSwitchView mKeypadChannelSwitchView;
     private final SelectInputView mSelectInputView;
     private final ProgramGuideSearchFragment mSearchFragment;
@@ -185,6 +222,7 @@
     private SafeDismissDialogFragment mCurrentDialog;
     private boolean mSetupFragmentActive;
     private boolean mNewSourcesFragmentActive;
+    private boolean mChannelBannerHiddenBySideFragment;
     private final Handler mHandler = new TvOverlayHandler(this);
 
     private @TvOverlayType int mOpenedOverlays;
@@ -195,15 +233,17 @@
     private OnBackStackChangedListener mOnBackStackChangedListener;
 
     public TvOverlayManager(MainActivity mainActivity, ChannelTuner channelTuner,
-            TunableTvView tvView, KeypadChannelSwitchView keypadChannelSwitchView,
-            ChannelBannerView channelBannerView, InputBannerView inputBannerView,
-            SelectInputView selectInputView, ViewGroup sceneContainer,
-            ProgramGuideSearchFragment searchFragment) {
+            TunableTvView tvView, TvOptionsManager optionsManager,
+            KeypadChannelSwitchView keypadChannelSwitchView, ChannelBannerView channelBannerView,
+            InputBannerView inputBannerView, SelectInputView selectInputView,
+            ViewGroup sceneContainer, ProgramGuideSearchFragment searchFragment) {
         mMainActivity = mainActivity;
         mChannelTuner = channelTuner;
         ApplicationSingletons singletons = TvApplication.getSingletons(mainActivity);
         mChannelDataManager = singletons.getChannelDataManager();
         mInputManager = singletons.getTvInputManagerHelper();
+        mTvView = tvView;
+        mChannelBannerView = channelBannerView;
         mKeypadChannelSwitchView = keypadChannelSwitchView;
         mSelectInputView = selectInputView;
         mSearchFragment = searchFragment;
@@ -225,7 +265,8 @@
         });
         // Menu
         MenuView menuView = (MenuView) mainActivity.findViewById(R.id.menu);
-        mMenu = new Menu(mainActivity, tvView, menuView, new MenuRowFactory(mainActivity, tvView),
+        mMenu = new Menu(mainActivity, tvView, optionsManager, menuView,
+                new MenuRowFactory(mainActivity, tvView),
                 new Menu.OnMenuVisibilityChangeListener() {
                     @Override
                     public void onMenuVisibilityChange(boolean visible) {
@@ -249,7 +290,7 @@
                 new Runnable() {
                     @Override
                     public void run() {
-                        mMainActivity.showChannelBannerIfHiddenBySideFragment();
+                        showChannelBannerIfHiddenBySideFragment();
                         onOverlayClosed(OVERLAY_TYPE_SIDE_FRAGMENT);
                     }
                 });
@@ -320,6 +361,9 @@
     public void release() {
         mMenu.release();
         mHandler.removeCallbacksAndMessages(null);
+        if (mKeypadChannelSwitchView != null) {
+            mKeypadChannelSwitchView.setChannels(null);
+        }
     }
 
     /**
@@ -436,6 +480,13 @@
         onOverlayOpened(OVERLAY_TYPE_DIALOG);
     }
 
+    /**
+     * Should be called by {@link MainActivity} when the currently browsable channels are updated.
+     */
+    public void onBrowsableChannelsUpdated() {
+        mKeypadChannelSwitchView.setChannels(mChannelTuner.getBrowsableChannelList());
+    }
+
     private void runAfterSideFragmentsAreClosed(final Runnable runnable) {
         if (mSideFragmentManager.isSidePanelVisible()) {
             // When the side panel is closing, it closes all the fragments, so the new fragment
@@ -541,7 +592,7 @@
      * Shows DVR manager.
      */
     public void showDvrManager() {
-        Intent intent = new Intent(mMainActivity, DvrActivity.class);
+        Intent intent = new Intent(mMainActivity, DvrBrowseActivity.class);
         mMainActivity.startActivity(intent);
     }
 
@@ -564,18 +615,34 @@
     }
 
     /**
+     * Shows DVR history dialog.
+     */
+    public void showDvrHistoryDialog() {
+        showDialogFragment(DvrHistoryDialogFragment.DIALOG_TAG,
+                new DvrHistoryDialogFragment(), false);
+    }
+
+    /**
      * Shows banner view.
      */
     public void showBanner() {
         mTransitionManager.goToChannelBannerScene();
     }
 
-    public void showKeypadChannelSwitch() {
-        hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_SCENE
-                | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_SIDE_PANELS
-                | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_DIALOG
-                | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_FRAGMENT);
-        mTransitionManager.goToKeypadChannelSwitchScene();
+    /**
+     * Pops up the KeypadChannelSwitchView with the given key input event.
+     *
+     * @param keyCode A key code of the key event.
+     */
+    public void showKeypadChannelSwitch(int keyCode) {
+        if (mChannelTuner.areAllChannelsLoaded()) {
+            hideOverlays(TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_SCENE
+                    | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_SIDE_PANELS
+                    | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_DIALOG
+                    | TvOverlayManager.FLAG_HIDE_OVERLAYS_KEEP_FRAGMENT);
+            mTransitionManager.goToKeypadChannelSwitchScene();
+            mKeypadChannelSwitchView.onNumberKeyUp(keyCode - KeyEvent.KEYCODE_0);
+        }
     }
 
     /**
@@ -619,6 +686,31 @@
     }
 
     /**
+     * Shows/hides the program guide according to it's hidden or shown now.
+     *
+     * @return {@code true} if program guide is going to be shown, otherwise {@code false}.
+     */
+    public boolean toggleProgramGuide() {
+        if (mProgramGuide.isActive()) {
+            mProgramGuide.onBackPressed();
+            return false;
+        } else {
+            showProgramGuide();
+            return true;
+        }
+    }
+
+    /**
+     * Sets blocking content rating of the currently playing TV channel.
+     */
+    public void setBlockingContentRating(TvContentRating rating) {
+        if (!mMainActivity.isChannelChangeKeyDownReceived()) {
+            mChannelBannerView.setBlockingContentRating(rating);
+            updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK);
+        }
+    }
+
+    /**
      * Hides all the opened overlays according to the flags.
      */
     // TODO: Add test for this method.
@@ -631,12 +723,12 @@
         } else {
             if (mCurrentDialog != null) {
                 if (mCurrentDialog instanceof PinDialogFragment) {
-                    // The result listener of PinDialogFragment could call MenuView when
-                    // the dialog is dismissed. In order not to call it, set the result listener
-                    // to null.
-                    ((PinDialogFragment) mCurrentDialog).setResultListener(null);
+                    // We don't want any OnPinCheckedListener is triggered to prevent any possible
+                    // side effects. Dismisses the dialog silently.
+                    ((PinDialogFragment) mCurrentDialog).dismissSilently();
+                } else {
+                    mCurrentDialog.dismiss();
                 }
-                mCurrentDialog.dismiss();
             }
             mPendingDialogActionQueue.clear();
             mCurrentDialog = null;
@@ -674,7 +766,7 @@
         }
         if ((flags & FLAG_HIDE_OVERLAYS_KEEP_SIDE_PANELS) != 0) {
             // Keeps side panels.
-        } else if (mSideFragmentManager.isSidePanelVisible()) {
+        } else if (mSideFragmentManager.isActive()) {
             if ((flags & FLAG_HIDE_OVERLAYS_KEEP_SIDE_PANEL_HISTORY) != 0) {
                 mSideFragmentManager.hideSidePanel(withAnimation);
             } else {
@@ -701,6 +793,83 @@
                 || mNewSourcesFragmentActive;
     }
 
+    /**
+     * Updates and shows channel banner if it's needed.
+     */
+    public void updateChannelBannerAndShowIfNeeded(@ChannelBannerUpdateReason int reason) {
+        if(DEBUG) Log.d(TAG, "updateChannelBannerAndShowIfNeeded(reason=" + reason + ")");
+        if (mMainActivity.isChannelChangeKeyDownReceived()
+                && reason != UPDATE_CHANNEL_BANNER_REASON_TUNE
+                && reason != UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST) {
+            // Tuning is still ongoing, no need to update banner for other reasons
+            return;
+        }
+        if (!mChannelTuner.isCurrentChannelPassthrough()) {
+            int lockType = ChannelBannerView.LOCK_NONE;
+            if (reason == UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST) {
+                if (mMainActivity.getParentalControlSettings().isParentalControlsEnabled()
+                        && mMainActivity.getCurrentChannel().isLocked()) {
+                    lockType = ChannelBannerView.LOCK_CHANNEL_INFO;
+                } else {
+                    // Do not show detailed program information while fast-tuning.
+                    lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
+                }
+            } else if (reason == UPDATE_CHANNEL_BANNER_REASON_TUNE) {
+                if (mMainActivity.getParentalControlSettings().isParentalControlsEnabled()) {
+                    if (mMainActivity.getCurrentChannel().isLocked()) {
+                        lockType = ChannelBannerView.LOCK_CHANNEL_INFO;
+                    } else {
+                        // If parental control is turned on,
+                        // assumes that program is locked by default and waits for onContentAllowed.
+                        lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
+                    }
+                }
+            } else if (mTvView.isScreenBlocked()) {
+                lockType = ChannelBannerView.LOCK_CHANNEL_INFO;
+            } else if (mTvView.isContentBlocked() || (mMainActivity.getParentalControlSettings()
+                    .isParentalControlsEnabled() && !mTvView.isVideoOrAudioAvailable())) {
+                // If the parental control is enabled, do not show the program detail until the
+                // video becomes available.
+                lockType = ChannelBannerView.LOCK_PROGRAM_DETAIL;
+            }
+            // If lock type is not changed, we don't need to update channel banner by parental
+            // control.
+            int previousLockType = mChannelBannerView.setLockType(lockType);
+            if (previousLockType == lockType
+                    && reason == UPDATE_CHANNEL_BANNER_REASON_LOCK_OR_UNLOCK) {
+                return;
+            } else if (reason == UPDATE_CHANNEL_BANNER_REASON_UPDATE_STREAM_INFO) {
+                mChannelBannerView.updateStreamInfo(mTvView);
+                // If parental control is enabled, we shows program description when the video is
+                // available, instead of tuning. Therefore we need to check it here if the program
+                // description is previously hidden by parental control.
+                if (previousLockType == ChannelBannerView.LOCK_PROGRAM_DETAIL &&
+                        lockType != ChannelBannerView.LOCK_PROGRAM_DETAIL) {
+                    mChannelBannerView.updateViews(false);
+                }
+            } else {
+                mChannelBannerView.updateViews(reason == UPDATE_CHANNEL_BANNER_REASON_TUNE
+                        || reason == UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST);
+            }
+        }
+        boolean needToShowBanner = (reason == UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW
+                || reason == UPDATE_CHANNEL_BANNER_REASON_TUNE
+                || reason == UPDATE_CHANNEL_BANNER_REASON_TUNE_FAST);
+        if (needToShowBanner && !mMainActivity.willShowOverlayUiWhenResume()
+                && getCurrentDialog() == null
+                && !isSetupFragmentActive()
+                && !isNewSourcesFragmentActive()) {
+            if (mChannelTuner.getCurrentChannel() == null) {
+                mChannelBannerHiddenBySideFragment = false;
+            } else if (getSideFragmentManager().isActive()) {
+                mChannelBannerHiddenBySideFragment = true;
+            } else {
+                mChannelBannerHiddenBySideFragment = false;
+                showBanner();
+            }
+        }
+    }
+
     @TvOverlayType private int convertSceneToOverlayType(@SceneType int sceneType) {
         switch (sceneType) {
             case TvTransitionManager.SCENE_TYPE_CHANNEL_BANNER:
@@ -749,6 +918,18 @@
         }
     }
 
+    /**
+     * Shows the channel banner if it was hidden from the side fragment.
+     *
+     * <p>When the side fragment is visible, showing the channel banner should be put off until the
+     * side fragment is closed even though the channel changes.
+     */
+    private void showChannelBannerIfHiddenBySideFragment() {
+        if (mChannelBannerHiddenBySideFragment) {
+            updateChannelBannerAndShowIfNeeded(UPDATE_CHANNEL_BANNER_REASON_FORCE_SHOW);
+        }
+    }
+
     private String toBinaryString(int value) {
         return String.format("0b%" + NUM_OVERLAY_TYPES + "s", Integer.toBinaryString(value))
                 .replace(' ', '0');
@@ -843,6 +1024,7 @@
                     timeShiftManager.play();
                     showMenu(Menu.REASON_PLAY_CONTROLS_PLAY);
                     break;
+                case KeyEvent.KEYCODE_MEDIA_STOP:
                 case KeyEvent.KEYCODE_MEDIA_PAUSE:
                     timeShiftManager.pause();
                     showMenu(Menu.REASON_PLAY_CONTROLS_PAUSE);
@@ -916,7 +1098,7 @@
             }
             if (mMenu.isActive()) {
                 if (KeypadChannelSwitchView.isChannelNumberKey(keyCode)) {
-                    mMainActivity.showKeypadChannelSwitchView(keyCode);
+                    showKeypadChannelSwitch(keyCode);
                     return MainActivity.KEY_EVENT_HANDLER_RESULT_HANDLED;
                 }
                 return MainActivity.KEY_EVENT_HANDLER_RESULT_DISPATCH_TO_OVERLAY;
@@ -971,6 +1153,7 @@
             case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
             case KeyEvent.KEYCODE_MEDIA_SKIP_FORWARD:
             case KeyEvent.KEYCODE_MEDIA_SKIP_BACKWARD:
+            case KeyEvent.KEYCODE_MEDIA_STOP:
                 return true;
         }
         return false;
diff --git a/src/com/android/tv/ui/TvTransitionManager.java b/src/com/android/tv/ui/TvTransitionManager.java
index 52e96cc..628bbb7 100644
--- a/src/com/android/tv/ui/TvTransitionManager.java
+++ b/src/com/android/tv/ui/TvTransitionManager.java
@@ -129,8 +129,8 @@
     public void goToSelectInputScene() {
         initIfNeeded();
         if (mCurrentScene != mSelectInputScene) {
-            transitionTo(mSelectInputScene);
             mSelectInputView.setCurrentChannel(mMainActivity.getCurrentChannel());
+            transitionTo(mSelectInputScene);
         }
     }
 
diff --git a/src/com/android/tv/ui/TvViewUiManager.java b/src/com/android/tv/ui/TvViewUiManager.java
index bf874fc..f042987 100644
--- a/src/com/android/tv/ui/TvViewUiManager.java
+++ b/src/com/android/tv/ui/TvViewUiManager.java
@@ -24,21 +24,19 @@
 import android.animation.TypeEvaluator;
 import android.animation.ValueAnimator;
 import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.hardware.display.DisplayManager;
+import android.os.Build;
 import android.os.Handler;
 import android.os.Message;
 import android.preference.PreferenceManager;
 import android.util.Log;
 import android.util.Property;
 import android.view.Display;
-import android.view.Gravity;
-import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewGroup.MarginLayoutParams;
@@ -52,9 +50,8 @@
 import com.android.tv.util.TvSettings;
 
 /**
- * The TvViewUiManager is responsible for handling UI layouting and animation of main and PIP
- * TvViews. It also control the settings regarding TvView UI such as display mode, PIP layout,
- * and PIP size.
+ * The TvViewUiManager is responsible for handling UI layouting and animation of main TvView.
+ * It also control the settings regarding TvView UI such as display mode.
  */
 public class TvViewUiManager {
     private static final String TAG = "TvViewManager";
@@ -69,42 +66,44 @@
     private final Resources mResources;
     private final FrameLayout mContentView;
     private final TunableTvView mTvView;
-    private final TunableTvView mPipView;
     private final TvOptionsManager mTvOptionsManager;
-    private final int mTvViewPapWidth;
     private final int mTvViewShrunkenStartMargin;
     private final int mTvViewShrunkenEndMargin;
-    private final int mTvViewPapStartMargin;
-    private final int mTvViewPapEndMargin;
     private int mWindowWidth;
     private int mWindowHeight;
-    private final int mPipViewHorizontalMargin;
-    private final int mPipViewTopMargin;
-    private final int mPipViewBottomMargin;
     private final SharedPreferences mSharedPreferences;
     private final TimeInterpolator mLinearOutSlowIn;
     private final TimeInterpolator mFastOutLinearIn;
-    private final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch(msg.what) {
-                case MSG_SET_LAYOUT_PARAMS:
-                    FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) msg.obj;
-                    if (DEBUG) {
-                        Log.d(TAG, "setFixedSize: w=" + layoutParams.width + " h="
-                                + layoutParams.height);
+    private final Handler mHandler =
+            new Handler() {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case MSG_SET_LAYOUT_PARAMS:
+                            FrameLayout.LayoutParams layoutParams =
+                                    (FrameLayout.LayoutParams) msg.obj;
+                            if (DEBUG) {
+                                Log.d(
+                                        TAG,
+                                        "setFixedSize: w="
+                                                + layoutParams.width
+                                                + " h="
+                                                + layoutParams.height);
+                            }
+                            mTvView.setTvViewLayoutParams(layoutParams);
+                            mTvView.setLayoutParams(mTvViewFrame);
+                            // Smooth PIP size change, we don't change surface size when
+                            // isInPictureInPictureMode is true.
+                            if (!Features.PICTURE_IN_PICTURE.isEnabled(mContext)
+                                    || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+                                            && !((Activity) mContext).isInPictureInPictureMode())) {
+                                mTvView.setFixedSurfaceSize(
+                                        layoutParams.width, layoutParams.height);
+                            }
+                            break;
                     }
-                    mTvView.setLayoutParams(layoutParams);
-                    // Smooth PIP size change, we don't change surface size when
-                    // isInPictureInPictureMode is true.
-                    if (!Features.PICTURE_IN_PICTURE.isEnabled(mContext)
-                            || !((Activity) mContext).isInPictureInPictureMode()) {
-                        mTvView.setFixedSurfaceSize(layoutParams.width, layoutParams.height);
-                    }
-                    break;
-            }
-        }
-    };
+                }
+            };
     private int mDisplayMode;
     // Used to restore the previous state from ShrunkenTvView state.
     private int mTvViewStartMarginBeforeShrunken;
@@ -113,16 +112,13 @@
     private boolean mIsUnderShrunkenTvView;
     private int mTvViewStartMargin;
     private int mTvViewEndMargin;
-    private int mPipLayout;
-    private int mPipSize;
-    private boolean mPipStarted;
     private ObjectAnimator mTvViewAnimator;
     private FrameLayout.LayoutParams mTvViewLayoutParams;
     // TV view's position when the display mode is FULL. It is used to compute PIP location relative
     // to TV view's position.
-    private MarginLayoutParams mTvViewFrame;
-    private MarginLayoutParams mLastAnimatedTvViewFrame;
-    private MarginLayoutParams mOldTvViewFrame;
+    private FrameLayout.LayoutParams mTvViewFrame;
+    private FrameLayout.LayoutParams mLastAnimatedTvViewFrame;
+    private FrameLayout.LayoutParams mOldTvViewFrame;
     private ObjectAnimator mBackgroundAnimator;
     private int mBackgroundColor;
     private int mAppliedDisplayedMode = DisplayMode.MODE_NOT_DEFINED;
@@ -130,12 +126,11 @@
     private int mAppliedTvViewEndMargin;
     private float mAppliedVideoDisplayAspectRatio;
 
-    public TvViewUiManager(Context context, TunableTvView tvView, TunableTvView pipView,
+    public TvViewUiManager(Context context, TunableTvView tvView,
             FrameLayout contentView, TvOptionsManager tvOptionManager) {
         mContext = context;
         mResources = mContext.getResources();
         mTvView = tvView;
-        mPipView = pipView;
         mContentView = contentView;
         mTvOptionsManager = tvOptionManager;
 
@@ -147,18 +142,12 @@
         mWindowWidth = size.x;
         mWindowHeight = size.y;
 
-        // Have an assumption that PIP and TvView Shrinking happens only in full screen.
+        // Have an assumption that TvView Shrinking happens only in full screen.
         mTvViewShrunkenStartMargin = mResources
                 .getDimensionPixelOffset(R.dimen.shrunken_tvview_margin_start);
         mTvViewShrunkenEndMargin =
                 mResources.getDimensionPixelOffset(R.dimen.shrunken_tvview_margin_end)
                         + mResources.getDimensionPixelSize(R.dimen.side_panel_width);
-        int papMarginHorizontal = mResources
-                .getDimensionPixelOffset(R.dimen.papview_margin_horizontal);
-        int papSpacing = mResources.getDimensionPixelOffset(R.dimen.papview_spacing);
-        mTvViewPapWidth = (mWindowWidth - papSpacing) / 2 - papMarginHorizontal;
-        mTvViewPapStartMargin = papMarginHorizontal + mTvViewPapWidth + papSpacing;
-        mTvViewPapEndMargin = papMarginHorizontal;
         mTvViewFrame = createMarginLayoutParams(0, 0, 0, 0);
 
         mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
@@ -167,11 +156,6 @@
                 .loadInterpolator(mContext, android.R.interpolator.linear_out_slow_in);
         mFastOutLinearIn = AnimationUtils
                 .loadInterpolator(mContext, android.R.interpolator.fast_out_linear_in);
-
-        mPipViewHorizontalMargin = mResources
-                .getDimensionPixelOffset(R.dimen.pipview_margin_horizontal);
-        mPipViewTopMargin = mResources.getDimensionPixelOffset(R.dimen.pipview_margin_top);
-        mPipViewBottomMargin = mResources.getDimensionPixelOffset(R.dimen.pipview_margin_bottom);
     }
 
     public void onConfigurationChanged(final int windowWidth, final int windowHeight) {
@@ -200,18 +184,11 @@
      */
     public void startShrunkenTvView() {
         mIsUnderShrunkenTvView = true;
+        mTvView.setIsUnderShrunken(true);
 
         mTvViewStartMarginBeforeShrunken = mTvViewStartMargin;
         mTvViewEndMarginBeforeShrunken = mTvViewEndMargin;
-        if (mPipStarted && getPipLayout() == TvSettings.PIP_LAYOUT_SIDE_BY_SIDE) {
-            float sidePanelWidth = mResources.getDimensionPixelOffset(R.dimen.side_panel_width);
-            float factor = 1.0f - sidePanelWidth / mWindowWidth;
-            int startMargin = (int) (mTvViewPapStartMargin * factor);
-            int endMargin = (int) (mTvViewPapEndMargin * factor + sidePanelWidth);
-            setTvViewMargin(startMargin, endMargin);
-        } else {
-            setTvViewMargin(mTvViewShrunkenStartMargin, mTvViewShrunkenEndMargin);
-        }
+        setTvViewMargin(mTvViewShrunkenStartMargin, mTvViewShrunkenEndMargin);
         mDisplayModeBeforeShrunken = setDisplayMode(DisplayMode.MODE_NORMAL, false, true);
     }
 
@@ -221,6 +198,7 @@
      */
     public void endShrunkenTvView() {
         mIsUnderShrunkenTvView = false;
+        mTvView.setIsUnderShrunken(false);
         setTvViewMargin(mTvViewStartMarginBeforeShrunken, mTvViewEndMarginBeforeShrunken);
         setDisplayMode(mDisplayModeBeforeShrunken, false, true);
     }
@@ -296,9 +274,9 @@
     }
 
     /**
-     * Updates TvView. It is called when video resolution is updated.
+     * Updates TvView's aspect ratio. It should be called when video resolution is changed.
      */
-    public void updateTvView() {
+    public void updateTvAspectRatio() {
         applyDisplayMode(mTvView.getVideoDisplayAspectRatio(), false, false);
         if (mTvView.isVideoAvailable() && mTvView.isFadedOut()) {
             mTvView.fadeIn(mResources.getInteger(R.integer.tvview_fade_in_duration),
@@ -327,120 +305,6 @@
     }
 
     /**
-     * Returns the current PIP layout. The layout should be one of
-     * {@link TvSettings#PIP_LAYOUT_BOTTOM_RIGHT}, {@link TvSettings#PIP_LAYOUT_TOP_RIGHT},
-     * {@link TvSettings#PIP_LAYOUT_TOP_LEFT}, {@link TvSettings#PIP_LAYOUT_BOTTOM_LEFT} and
-     * {@link TvSettings#PIP_LAYOUT_SIDE_BY_SIDE}.
-     */
-    public int getPipLayout() {
-        return mPipLayout;
-    }
-
-    /**
-     * Sets the PIP layout. The layout should be one of
-     * {@link TvSettings#PIP_LAYOUT_BOTTOM_RIGHT}, {@link TvSettings#PIP_LAYOUT_TOP_RIGHT},
-     * {@link TvSettings#PIP_LAYOUT_TOP_LEFT}, {@link TvSettings#PIP_LAYOUT_BOTTOM_LEFT} and
-     * {@link TvSettings#PIP_LAYOUT_SIDE_BY_SIDE}.
-     *
-     * @param storeInPreference if true, the stored value will be restored by
-     *                          {@link #restorePipLayout()}.
-     */
-    public void setPipLayout(int pipLayout, boolean storeInPreference) {
-        mPipLayout = pipLayout;
-        if (storeInPreference) {
-            TvSettings.setPipLayout(mContext, pipLayout);
-        }
-        updatePipView(mTvViewFrame);
-        if (mPipLayout == TvSettings.PIP_LAYOUT_SIDE_BY_SIDE) {
-            setTvViewMargin(mTvViewPapStartMargin, mTvViewPapEndMargin);
-            setDisplayMode(DisplayMode.MODE_NORMAL, false, false);
-        } else {
-            setTvViewMargin(0, 0);
-            restoreDisplayMode(false);
-        }
-        mTvOptionsManager.onPipLayoutChanged(pipLayout);
-    }
-
-    /**
-     * Restores the PIP layout which {@link #setPipLayout} lastly stores.
-     */
-    public void restorePipLayout() {
-        setPipLayout(TvSettings.getPipLayout(mContext), false);
-    }
-
-    /**
-     * Called when PIP is started.
-     */
-    public void onPipStart() {
-        mPipStarted = true;
-        updatePipView();
-        mPipView.setVisibility(View.VISIBLE);
-    }
-
-    /**
-     * Called when PIP is stopped.
-     */
-    public void onPipStop() {
-        setTvViewMargin(0, 0);
-        mPipView.setVisibility(View.GONE);
-        mPipStarted = false;
-    }
-
-    /**
-     * Called when PIP is resumed.
-     */
-    public void showPipForResume() {
-        mPipView.setVisibility(View.VISIBLE);
-    }
-
-    /**
-     * Called when PIP is paused.
-     */
-    public void hidePipForPause() {
-        if (mPipLayout != TvSettings.PIP_LAYOUT_SIDE_BY_SIDE) {
-            mPipView.setVisibility(View.GONE);
-        }
-    }
-
-    /**
-     * Updates PIP view. It is usually called, when video resolution in PIP is updated.
-     */
-    public void updatePipView() {
-        updatePipView(mTvViewFrame);
-    }
-
-    /**
-     * Returns the size of the PIP view.
-     */
-    public int getPipSize() {
-        return mPipSize;
-    }
-
-    /**
-     * Sets PIP size and applies it immediately.
-     *
-     * @param pipSize           PIP size. The value should be one of {@link TvSettings#PIP_SIZE_BIG}
-     *                          and {@link TvSettings#PIP_SIZE_SMALL}.
-     * @param storeInPreference if true, the stored value will be restored by
-     *                          {@link #restorePipSize()}.
-     */
-    public void setPipSize(int pipSize, boolean storeInPreference) {
-        mPipSize = pipSize;
-        if (storeInPreference) {
-            TvSettings.setPipSize(mContext, pipSize);
-        }
-        updatePipView(mTvViewFrame);
-        mTvOptionsManager.onPipSizeChanged(pipSize);
-    }
-
-    /**
-     * Restores the PIP size which {@link #setPipSize} lastly stores.
-     */
-    public void restorePipSize() {
-        setPipSize(TvSettings.getPipSize(mContext), false);
-    }
-
-    /**
      * This margins will be applied when applyDisplayMode is called.
      */
     private void setTvViewMargin(int tvViewStartMargin, int tvViewEndMargin) {
@@ -488,14 +352,14 @@
     }
 
     private void setTvViewPosition(final FrameLayout.LayoutParams layoutParams,
-            MarginLayoutParams tvViewFrame, boolean animate) {
+            FrameLayout.LayoutParams tvViewFrame, boolean animate) {
         if (DEBUG) {
             Log.d(TAG, "setTvViewPosition: w=" + layoutParams.width + " h=" + layoutParams.height
                     + " s=" + layoutParams.getMarginStart() + " t=" + layoutParams.topMargin
                     + " e=" + layoutParams.getMarginEnd() + " b=" + layoutParams.bottomMargin
                     + " animate=" + animate);
         }
-        MarginLayoutParams oldTvViewFrame = mTvViewFrame;
+        FrameLayout.LayoutParams oldTvViewFrame = mTvViewFrame;
         mTvViewLayoutParams = layoutParams;
         mTvViewFrame = tvViewFrame;
         if (animate) {
@@ -503,11 +367,11 @@
             if (mTvViewAnimator.isStarted()) {
                 // Cancel the current animation and start new one.
                 mTvViewAnimator.cancel();
-                mOldTvViewFrame = mLastAnimatedTvViewFrame;
+                mOldTvViewFrame = new FrameLayout.LayoutParams(mLastAnimatedTvViewFrame);
             } else {
-                mOldTvViewFrame = oldTvViewFrame;
+                mOldTvViewFrame = new FrameLayout.LayoutParams(oldTvViewFrame);
             }
-            mTvViewAnimator.setObjectValues(mTvView.getLayoutParams(), layoutParams);
+            mTvViewAnimator.setObjectValues(mTvView.getTvViewLayoutParams(), layoutParams);
             mTvViewAnimator.setEvaluator(new TypeEvaluator<FrameLayout.LayoutParams>() {
                 FrameLayout.LayoutParams lp;
                 @Override
@@ -517,7 +381,7 @@
                         lp = new FrameLayout.LayoutParams(0, 0);
                         lp.gravity = startValue.gravity;
                     }
-                    interpolateMarginsRelative(lp, startValue, endValue, fraction);
+                    interpolateMargins(lp, startValue, endValue, fraction);
                     return lp;
                 }
             });
@@ -538,115 +402,9 @@
                 mHandler.removeMessages(MSG_SET_LAYOUT_PARAMS);
                 mHandler.obtainMessage(MSG_SET_LAYOUT_PARAMS, layoutParams).sendToTarget();
             } else {
-                mTvView.setLayoutParams(layoutParams);
+                mTvView.setTvViewLayoutParams(layoutParams);
+                mTvView.setLayoutParams(mTvViewFrame);
             }
-            updatePipView(mTvViewFrame);
-        }
-    }
-
-    /**
-     * The redlines assume that the ratio of the TV screen is 16:9. If the radio is not 16:9, the
-     * layout of PAP can be broken.
-     */
-    @SuppressLint("RtlHardcoded")
-    private void updatePipView(MarginLayoutParams tvViewFrame) {
-        if (!mPipStarted) {
-            return;
-        }
-        int width;
-        int height;
-        int startMargin;
-        int endMargin;
-        int topMargin;
-        int bottomMargin;
-        int gravity;
-
-        if (mPipLayout == TvSettings.PIP_LAYOUT_SIDE_BY_SIDE) {
-            gravity = Gravity.CENTER_VERTICAL | Gravity.START;
-            height = tvViewFrame.height;
-            float videoDisplayAspectRatio = mPipView.getVideoDisplayAspectRatio();
-            if (videoDisplayAspectRatio <= 0f) {
-                width = tvViewFrame.width;
-            } else {
-                width = (int) (height * videoDisplayAspectRatio);
-                if (width > tvViewFrame.width) {
-                    width = tvViewFrame.width;
-                }
-            }
-            startMargin = mResources.getDimensionPixelOffset(R.dimen.papview_margin_horizontal)
-                    * tvViewFrame.width / mTvViewPapWidth + (tvViewFrame.width - width) / 2;
-            endMargin = 0;
-            topMargin = 0;
-            bottomMargin = 0;
-        } else {
-            int tvViewWidth = tvViewFrame.width;
-            int tvViewHeight = tvViewFrame.height;
-            int tvStartMargin = tvViewFrame.getMarginStart();
-            int tvEndMargin = tvViewFrame.getMarginEnd();
-            int tvTopMargin = tvViewFrame.topMargin;
-            int tvBottomMargin = tvViewFrame.bottomMargin;
-            float horizontalScaleFactor = (float) tvViewWidth / mWindowWidth;
-            float verticalScaleFactor = (float) tvViewHeight / mWindowHeight;
-
-            int maxWidth;
-            if (mPipSize == TvSettings.PIP_SIZE_SMALL) {
-                maxWidth = (int) (mResources.getDimensionPixelSize(R.dimen.pipview_small_size_width)
-                        * horizontalScaleFactor);
-                height = (int) (mResources.getDimensionPixelSize(R.dimen.pipview_small_size_height)
-                        * verticalScaleFactor);
-            } else if (mPipSize == TvSettings.PIP_SIZE_BIG) {
-                maxWidth = (int) (mResources.getDimensionPixelSize(R.dimen.pipview_large_size_width)
-                        * horizontalScaleFactor);
-                height = (int) (mResources.getDimensionPixelSize(R.dimen.pipview_large_size_height)
-                        * verticalScaleFactor);
-            } else {
-                throw new IllegalArgumentException("Invalid PIP size: " + mPipSize);
-            }
-            float videoDisplayAspectRatio = mPipView.getVideoDisplayAspectRatio();
-            if (videoDisplayAspectRatio <= 0f) {
-                width = maxWidth;
-            } else {
-                width = (int) (height * videoDisplayAspectRatio);
-                if (width > maxWidth) {
-                    width = maxWidth;
-                }
-            }
-
-            startMargin = tvStartMargin + (int) (mPipViewHorizontalMargin * horizontalScaleFactor);
-            endMargin = tvEndMargin + (int) (mPipViewHorizontalMargin * horizontalScaleFactor);
-            topMargin = tvTopMargin + (int) (mPipViewTopMargin * verticalScaleFactor);
-            bottomMargin = tvBottomMargin + (int) (mPipViewBottomMargin * verticalScaleFactor);
-
-            switch (mPipLayout) {
-                case TvSettings.PIP_LAYOUT_TOP_LEFT:
-                    gravity = Gravity.TOP | Gravity.LEFT;
-                    break;
-                case TvSettings.PIP_LAYOUT_TOP_RIGHT:
-                    gravity = Gravity.TOP | Gravity.RIGHT;
-                    break;
-                case TvSettings.PIP_LAYOUT_BOTTOM_LEFT:
-                    gravity = Gravity.BOTTOM | Gravity.LEFT;
-                    break;
-                case TvSettings.PIP_LAYOUT_BOTTOM_RIGHT:
-                    gravity = Gravity.BOTTOM | Gravity.RIGHT;
-                    break;
-                default:
-                    throw new IllegalArgumentException("Invalid PIP location: " + mPipLayout);
-            }
-        }
-
-        FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mPipView.getLayoutParams();
-        if (lp.width != width || lp.height != height || lp.getMarginStart() != startMargin
-                || lp.getMarginEnd() != endMargin || lp.topMargin != topMargin
-                || lp.bottomMargin != bottomMargin || lp.gravity != gravity) {
-            lp.width = width;
-            lp.height = height;
-            lp.setMarginStart(startMargin);
-            lp.setMarginEnd(endMargin);
-            lp.topMargin = topMargin;
-            lp.bottomMargin = bottomMargin;
-            lp.gravity = gravity;
-            mPipView.setLayoutParams(lp);
         }
     }
 
@@ -663,7 +421,7 @@
         // because TvView may request layout itself during animation and layout SurfaceView with
         // its own parameters when TvInputService requests to do so.
         mTvViewAnimator = new ObjectAnimator();
-        mTvViewAnimator.setTarget(mTvView);
+        mTvViewAnimator.setTarget(mTvView.getTvView());
         mTvViewAnimator.setProperty(
                 Property.of(FrameLayout.class, ViewGroup.LayoutParams.class, "layoutParams"));
         mTvViewAnimator.setDuration(mResources.getInteger(R.integer.tvview_anim_duration));
@@ -693,10 +451,10 @@
             @Override
             public void onAnimationUpdate(ValueAnimator animator) {
                 float fraction = animator.getAnimatedFraction();
-                mLastAnimatedTvViewFrame = new MarginLayoutParams(0, 0);
-                interpolateMarginsRelative(mLastAnimatedTvViewFrame,
+                mLastAnimatedTvViewFrame = (FrameLayout.LayoutParams) mTvView.getLayoutParams();
+                interpolateMargins(mLastAnimatedTvViewFrame,
                         mOldTvViewFrame, mTvViewFrame, fraction);
-                updatePipView(mLastAnimatedTvViewFrame);
+                mTvView.setLayoutParams(mLastAnimatedTvViewFrame);
             }
         });
     }
@@ -745,66 +503,58 @@
         }
         int availableAreaWidth = mWindowWidth - mTvViewStartMargin - mTvViewEndMargin;
         int availableAreaHeight = availableAreaWidth * mWindowHeight / mWindowWidth;
-        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(0, 0,
-                ((FrameLayout.LayoutParams) mTvView.getLayoutParams()).gravity);
         int displayMode = mDisplayMode;
-        double availableAreaRatio = 0;
-        double videoRatio = 0;
+        float availableAreaRatio = 0;
         if (availableAreaWidth <= 0 || availableAreaHeight <= 0) {
             displayMode = DisplayMode.MODE_FULL;
             Log.w(TAG, "Some resolution info is missing during applyDisplayMode. ("
                     + "availableAreaWidth=" + availableAreaWidth + ", availableAreaHeight="
                     + availableAreaHeight + ")");
         } else {
-            availableAreaRatio = (double) availableAreaWidth / availableAreaHeight;
-            videoRatio = videoDisplayAspectRatio;
+            availableAreaRatio = (float) availableAreaWidth / availableAreaHeight;
         }
-
-        int tvViewFrameTop = (mWindowHeight - availableAreaHeight) / 2;
-        MarginLayoutParams tvViewFrame = createMarginLayoutParams(
-                mTvViewStartMargin, mTvViewEndMargin, tvViewFrameTop, tvViewFrameTop);
-        layoutParams.width = availableAreaWidth;
-        layoutParams.height = availableAreaHeight;
+        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(0, 0,
+                ((FrameLayout.LayoutParams) mTvView.getTvViewLayoutParams()).gravity);
         switch (displayMode) {
-            case DisplayMode.MODE_FULL:
-                layoutParams.width = availableAreaWidth;
-                layoutParams.height = availableAreaHeight;
-                break;
             case DisplayMode.MODE_ZOOM:
-                if (videoRatio < availableAreaRatio) {
+                if (videoDisplayAspectRatio < availableAreaRatio) {
                     // Y axis will be clipped.
                     layoutParams.width = availableAreaWidth;
-                    layoutParams.height = (int) Math.round(availableAreaWidth / videoRatio);
+                    layoutParams.height = Math.round(availableAreaWidth / videoDisplayAspectRatio);
                 } else {
                     // X axis will be clipped.
-                    layoutParams.width = (int) Math.round(availableAreaHeight * videoRatio);
+                    layoutParams.width = Math.round(availableAreaHeight * videoDisplayAspectRatio);
                     layoutParams.height = availableAreaHeight;
                 }
                 break;
             case DisplayMode.MODE_NORMAL:
-                if (videoRatio < availableAreaRatio) {
+                if (videoDisplayAspectRatio < availableAreaRatio) {
                     // X axis has black area.
-                    layoutParams.width = (int) Math.round(availableAreaHeight * videoRatio);
+                    layoutParams.width = Math.round(availableAreaHeight * videoDisplayAspectRatio);
                     layoutParams.height = availableAreaHeight;
                 } else {
                     // Y axis has black area.
                     layoutParams.width = availableAreaWidth;
-                    layoutParams.height = (int) Math.round(availableAreaWidth / videoRatio);
+                    layoutParams.height = Math.round(availableAreaWidth / videoDisplayAspectRatio);
                 }
                 break;
+            case DisplayMode.MODE_FULL:
+            default:
+                layoutParams.width = availableAreaWidth;
+                layoutParams.height = availableAreaHeight;
+                break;
         }
-
         // FrameLayout has an issue with centering when left and right margins differ.
         // So stick to Gravity.START | Gravity.CENTER_VERTICAL.
-        int marginStart = mTvViewStartMargin + (availableAreaWidth - layoutParams.width) / 2;
+        int marginStart = (availableAreaWidth - layoutParams.width) / 2;
         layoutParams.setMarginStart(marginStart);
-        // Set marginEnd as well because setTvViewPosition uses both start/end margin.
-        layoutParams.setMarginEnd(mWindowWidth - layoutParams.width - marginStart);
-
+        int tvViewFrameTop = (mWindowHeight - availableAreaHeight) / 2;
+        FrameLayout.LayoutParams tvViewFrame = createMarginLayoutParams(
+                mTvViewStartMargin, mTvViewEndMargin, tvViewFrameTop, tvViewFrameTop);
+        setTvViewPosition(layoutParams, tvViewFrame, animate);
         setBackgroundColor(mResources.getColor(isTvViewFullScreen()
                 ? R.color.tvactivity_background : R.color.tvactivity_background_on_shrunken_tvview,
-                        null), layoutParams, animate);
-        setTvViewPosition(layoutParams, tvViewFrame, animate);
+                null), layoutParams, animate);
 
         // Update the current display mode.
         mTvOptionsManager.onDisplayModeChanged(displayMode);
@@ -814,7 +564,7 @@
         return (int) (start + (end - start) * fraction);
     }
 
-    private static void interpolateMarginsRelative(MarginLayoutParams out,
+    private static void interpolateMargins(MarginLayoutParams out,
             MarginLayoutParams startValue, MarginLayoutParams endValue, float fraction) {
         out.topMargin = interpolate(startValue.topMargin, endValue.topMargin, fraction);
         out.bottomMargin = interpolate(startValue.bottomMargin, endValue.bottomMargin, fraction);
@@ -825,9 +575,9 @@
         out.height = interpolate(startValue.height, endValue.height, fraction);
     }
 
-    private MarginLayoutParams createMarginLayoutParams(
+    private FrameLayout.LayoutParams createMarginLayoutParams(
             int startMargin, int endMargin, int topMargin, int bottomMargin) {
-        MarginLayoutParams lp = new MarginLayoutParams(0, 0);
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(0, 0);
         lp.setMarginStart(startMargin);
         lp.setMarginEnd(endMargin);
         lp.topMargin = topMargin;
@@ -836,4 +586,4 @@
         lp.height = mWindowHeight - topMargin - bottomMargin;
         return lp;
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/ui/sidepanel/ActionItem.java b/src/com/android/tv/ui/sidepanel/ActionItem.java
index 23aff91..cd70a88 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 @@
 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 @@
         } 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 d6ccdf6..341e435 100644
--- a/src/com/android/tv/ui/sidepanel/ClosedCaptionFragment.java
+++ b/src/com/android/tv/ui/sidepanel/ClosedCaptionFragment.java
@@ -18,6 +18,7 @@
 
 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 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 @@
     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 @@
         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 @@
                 @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 @@
     }
 
     @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 @@
         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 7613a9a..c274693 100644
--- a/src/com/android/tv/ui/sidepanel/CompoundButtonItem.java
+++ b/src/com/android/tv/ui/sidepanel/CompoundButtonItem.java
@@ -23,9 +23,12 @@
 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 @@
         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 @@
         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 9cc54ed..297e69d 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 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 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 @@
     @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 @@
         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 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 @@
 
         @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 0d189cc..f633fa5 100644
--- a/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java
+++ b/src/com/android/tv/ui/sidepanel/DeveloperOptionFragment.java
@@ -18,8 +18,6 @@
 
 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 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 @@
     @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 @@
                 }
             });
         }
-        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 @@
                 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 00f1642..4e47e75 100644
--- a/src/com/android/tv/ui/sidepanel/Item.java
+++ b/src/com/android/tv/ui/sidepanel/Item.java
@@ -24,6 +24,7 @@
 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 @@
     }
 
     /**
+     * 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 @@
      */
     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 dec017a..0000000
--- 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 e8033a2..6a5b510 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 @@
 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 @@
         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 @@
                             : 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 @@
             // 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 8df56cd..6bd921a 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.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 @@
     @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 @@
         return mListView.getSelectedPosition();
     }
 
-    public void setItems(List<Item> items) {
+    public void setItems(List<T> items) {
         mAdapter.reset(items);
     }
 
@@ -229,56 +227,50 @@
     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 @@
             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 @@
                 }
             }
         }
+    }
 
-        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 onUnbind() {
+            mItem.onUnbind();
+            mItem = null;
+            mAdapter = null;
+        }
+
+        @Override
+        public void onClick(View view) {
+            if (mItem instanceof RadioButtonItem) {
+                mAdapter.clearRadioGroup(mItem);
             }
-
-            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;
-            }
-
-            @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();
+            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 553cd9d..d02d3fb 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.FragmentTransaction;
 import android.os.Handler;
 import android.view.View;
+import android.view.ViewTreeObserver;
 
 import com.android.tv.R;
 
@@ -34,6 +35,7 @@
     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 @@
      * 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 @@
         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 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 @@
      * @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
similarity index 84%
rename from src/com/android/tv/ui/sidepanel/SimpleItem.java
rename to src/com/android/tv/ui/sidepanel/SimpleActionItem.java
index 52a5f13..42553b6 100644
--- a/src/com/android/tv/ui/sidepanel/SimpleItem.java
+++ b/src/com/android/tv/ui/sidepanel/SimpleActionItem.java
@@ -19,12 +19,12 @@
 /**
  * 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 aa349db..4b0e8e2 100644
--- a/src/com/android/tv/ui/sidepanel/SubMenuItem.java
+++ b/src/com/android/tv/ui/sidepanel/SubMenuItem.java
@@ -21,20 +21,11 @@
     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 ef9966a..06591b6 100644
--- a/src/com/android/tv/ui/sidepanel/SwitchItem.java
+++ b/src/com/android/tv/ui/sidepanel/SwitchItem.java
@@ -31,6 +31,11 @@
         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 da71292..9a4879f 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 @@
             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 6bc4793..7c8cecb 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.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 @@
     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 @@
     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 @@
         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 @@
             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 @@
         @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 f6612fd..4634b74 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 @@
 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
diff --git a/src/com/android/tv/util/AsyncDbTask.java b/src/com/android/tv/util/AsyncDbTask.java
index 7824364..477412e 100644
--- a/src/com/android/tv/util/AsyncDbTask.java
+++ b/src/com/android/tv/util/AsyncDbTask.java
@@ -31,7 +31,7 @@
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.data.Program;
-import com.android.tv.dvr.RecordedProgram;
+import com.android.tv.dvr.data.RecordedProgram;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -76,7 +76,7 @@
      *                                    accepted for execution
      * @throws NullPointerException       if command is null
      */
-    public static void execute(Runnable command) {
+    public static void executeOnDbThread(Runnable command) {
         DB_EXECUTOR.execute(command);
     }
 
diff --git a/src/com/android/tv/util/BitmapUtils.java b/src/com/android/tv/util/BitmapUtils.java
index d45a8dc..fbaab02 100644
--- a/src/com/android/tv/util/BitmapUtils.java
+++ b/src/com/android/tv/util/BitmapUtils.java
@@ -24,6 +24,7 @@
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.net.TrafficStats;
 import android.net.Uri;
 import android.support.annotation.NonNull;
 import android.text.TextUtils;
@@ -56,6 +57,12 @@
         return Bitmap.createScaledBitmap(bm, rect.right, rect.bottom, false);
     }
 
+    public static Bitmap getScaledMutableBitmap(Bitmap bm, int maxWidth, int maxHeight) {
+        Bitmap scaledBitmap = scaleBitmap(bm, maxWidth, maxHeight);
+        return scaledBitmap.isMutable() ? scaledBitmap
+                : scaledBitmap.copy(Bitmap.Config.ARGB_8888, true);
+    }
+
     private static Rect calculateNewSize(Bitmap bm, int maxWidth, int maxHeight) {
         final double ratio = maxHeight / (double) maxWidth;
         final double bmRatio = bm.getHeight() / (double) bm.getWidth();
@@ -89,6 +96,8 @@
         boolean isResourceUri = isContentResolverUri(uri);
         URLConnection urlConnection = null;
         InputStream inputStream = null;
+        final int oldTag = TrafficStats.getThreadStatsTag();
+        TrafficStats.setThreadStatsTag(NetworkTrafficTags.LOGO_FETCHER);
         try {
             if (isResourceUri) {
                 inputStream = context.getContentResolver().openInputStream(uri);
@@ -142,6 +151,7 @@
             return null;
         } finally {
             close(inputStream, urlConnection);
+            TrafficStats.setThreadStatsTag(oldTag);
         }
     }
 
diff --git a/src/com/android/tv/util/Debug.java b/src/com/android/tv/util/Debug.java
new file mode 100644
index 0000000..67a2683
--- /dev/null
+++ b/src/com/android/tv/util/Debug.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 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.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * A class only for help developers.
+ */
+public class Debug {
+    /**
+     * A threshold of start up time, when the start up time of Live TV is more than it,
+     * a warning will show to the developer.
+     */
+    public static final long TIME_START_UP_DURATION_THRESHOLD = TimeUnit.SECONDS.toMillis(6);
+    /**
+     * Tag for measuring start up time of Live TV.
+     */
+    public static final String TAG_START_UP_TIMER = "start_up_timer";
+
+    /**
+     * A global map for duration timers.
+     */
+    private final static Map<String, DurationTimer> sTimerMap = new HashMap<>();
+
+    /**
+     * Returns the global duration timer by tag.
+     */
+    public static DurationTimer getTimer(String tag) {
+        if (sTimerMap.get(tag) != null) {
+            return sTimerMap.get(tag);
+        }
+        DurationTimer timer = new DurationTimer(tag, true);
+        sTimerMap.put(tag, timer);
+        return timer;
+    }
+
+    /**
+     * Removes the global duration timer by tag.
+     */
+    public static DurationTimer removeTimer(String tag) {
+        return sTimerMap.remove(tag);
+    }
+}
diff --git a/src/com/android/tv/util/DurationTimer.java b/src/com/android/tv/util/DurationTimer.java
new file mode 100644
index 0000000..1f057bf
--- /dev/null
+++ b/src/com/android/tv/util/DurationTimer.java
@@ -0,0 +1,91 @@
+/*
+ * 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.util;
+
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.tv.common.BuildConfig;
+
+/**
+ * Times a duration.
+ */
+public final class DurationTimer {
+    private static final String TAG = "DurationTimer";
+    public static final long TIME_NOT_SET = -1;
+
+    private long mStartTimeMs = TIME_NOT_SET;
+    private String mTag = TAG;
+    private boolean mLogEngOnly;
+
+    public DurationTimer() { }
+
+    public DurationTimer(String tag, boolean logEngOnly) {
+        mTag = tag;
+        mLogEngOnly = logEngOnly;
+    }
+
+    /**
+     * Returns true if the timer is running.
+     */
+    public boolean isRunning() {
+        return mStartTimeMs != TIME_NOT_SET;
+    }
+
+    /**
+     * Start the timer.
+     */
+    public void start() {
+        mStartTimeMs = SystemClock.elapsedRealtime();
+    }
+
+    /**
+     * Returns true if timer is started.
+     */
+    public boolean isStarted() {
+        return mStartTimeMs != TIME_NOT_SET;
+    }
+
+    /**
+     * Returns the current duration in milliseconds or {@link #TIME_NOT_SET} if the timer is not
+     * running.
+     */
+    public long getDuration() {
+        return isRunning() ? SystemClock.elapsedRealtime() - mStartTimeMs : TIME_NOT_SET;
+    }
+
+    /**
+     * Stops the timer and resets its value to {@link #TIME_NOT_SET}.
+     *
+     * @return the current duration in milliseconds or {@link #TIME_NOT_SET} if the timer is not
+     * running.
+     */
+    public long reset() {
+        long duration = getDuration();
+        mStartTimeMs = TIME_NOT_SET;
+        return duration;
+    }
+
+    /**
+     * Adds information and duration time to the log.
+     */
+    public void log(String message) {
+        if (isRunning() && (!mLogEngOnly || BuildConfig.ENG)) {
+            Log.i(mTag, message + " : " + getDuration() + "ms");
+        }
+    }
+}
diff --git a/src/com/android/tv/util/ImageLoader.java b/src/com/android/tv/util/ImageLoader.java
index 04bb478..86bb94c 100644
--- a/src/com/android/tv/util/ImageLoader.java
+++ b/src/com/android/tv/util/ImageLoader.java
@@ -292,7 +292,8 @@
          * Checks if a reload would be needed if the results of other was available.
          */
         private boolean isReloadNeeded(LoadBitmapTask other) {
-            return mMaxHeight >= other.mMaxHeight * 2 || mMaxWidth >= other.mMaxWidth * 2;
+            return (other.mMaxHeight != Integer.MAX_VALUE && mMaxHeight >= other.mMaxHeight * 2)
+                    || (other.mMaxWidth != Integer.MAX_VALUE && mMaxWidth >= other.mMaxWidth * 2);
         }
 
         @Nullable
diff --git a/src/com/android/tv/util/LocationUtils.java b/src/com/android/tv/util/LocationUtils.java
index 8e3b59e..d5d7bee 100644
--- a/src/com/android/tv/util/LocationUtils.java
+++ b/src/com/android/tv/util/LocationUtils.java
@@ -16,15 +16,20 @@
 
 package com.android.tv.util;
 
+import android.Manifest;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.location.Address;
 import android.location.Geocoder;
 import android.location.Location;
 import android.location.LocationListener;
 import android.location.LocationManager;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.tv.tuner.util.PostalCodeUtils;
 
 import java.io.IOException;
 import java.util.List;
@@ -39,6 +44,7 @@
 
     private static Context sApplicationContext;
     private static Address sAddress;
+    private static String sCountry;
     private static IOException sError;
 
     /**
@@ -59,6 +65,18 @@
         return null;
     }
 
+    /** Returns the current country. */
+    @NonNull
+    public static synchronized String getCurrentCountry(Context context) {
+        if (sCountry != null) {
+            return sCountry;
+        }
+        if (TextUtils.isEmpty(sCountry)) {
+            sCountry = context.getResources().getConfiguration().locale.getCountry();
+        }
+        return sCountry;
+    }
+
     private static void updateAddress(Location location) {
         if (DEBUG) Log.d(TAG, "Updating address with " + location);
         if (location == null) {
@@ -68,9 +86,14 @@
         try {
             List<Address> addresses = geocoder.getFromLocation(
                     location.getLatitude(), location.getLongitude(), 1);
-            if (addresses != null) {
+            if (addresses != null && !addresses.isEmpty()) {
                 sAddress = addresses.get(0);
                 if (DEBUG) Log.d(TAG, "Got " + sAddress);
+                try {
+                    PostalCodeUtils.updatePostalCode(sApplicationContext);
+                } catch (Exception e) {
+                    // Do nothing
+                }
             } else {
                 if (DEBUG) Log.d(TAG, "No address returned");
             }
diff --git a/src/com/android/tv/util/NetworkTrafficTags.java b/src/com/android/tv/util/NetworkTrafficTags.java
new file mode 100644
index 0000000..2dca613
--- /dev/null
+++ b/src/com/android/tv/util/NetworkTrafficTags.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+import android.net.TrafficStats;
+import android.support.annotation.NonNull;
+
+import java.util.concurrent.Executor;
+
+/** Constants for tagging network traffic in the Live channels app. */
+public final class NetworkTrafficTags {
+
+    public static final int DEFAULT_LIVE_CHANNELS = 1;
+    public static final int LOGO_FETCHER = 2;
+    public static final int HDHOMERUN = 3;
+    public static final int EPG_FETCH = 4;
+
+    /**
+     * An executor which simply wraps a provided delegate executor, but calls {@link
+     * TrafficStats#setThreadStatsTag(int)} before executing any task.
+     */
+    public static class TrafficStatsTaggingExecutor implements Executor {
+        private final Executor delegateExecutor;
+        private final int tag;
+
+        public TrafficStatsTaggingExecutor(Executor delegateExecutor, int tag) {
+            this.delegateExecutor = delegateExecutor;
+            this.tag = tag;
+        }
+
+        @Override
+        public void execute(final @NonNull Runnable command) {
+            // TODO(b/62038127): robolectric does not support lamdas in unbundled apps
+            delegateExecutor.execute(
+                    new Runnable() {
+                        @Override
+                        public void run() {
+                            TrafficStats.setThreadStatsTag(tag);
+                            try {
+                                command.run();
+                            } finally {
+                                TrafficStats.clearThreadStatsTag();
+                            }
+                        }
+                    });
+        }
+    }
+
+    private NetworkTrafficTags() {}
+}
diff --git a/src/com/android/tv/util/OnboardingUtils.java b/src/com/android/tv/util/OnboardingUtils.java
index 3040020..49b02b8 100644
--- a/src/com/android/tv/util/OnboardingUtils.java
+++ b/src/com/android/tv/util/OnboardingUtils.java
@@ -16,17 +16,10 @@
 
 package com.android.tv.util;
 
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.database.Cursor;
-import android.media.tv.TvContract.Channels;
 import android.net.Uri;
 import android.preference.PreferenceManager;
-import android.support.annotation.UiThread;
-
-import com.android.tv.TvApplication;
-import com.android.tv.data.ChannelDataManager;
 
 /**
  * A utility class related to onboarding experience.
@@ -82,41 +75,11 @@
     }
 
     /**
-     * Checks whether the onboarding screen should be shown or not.
-     */
-    public static boolean needToShowOnboarding(Context context) {
-        return isFirstRunWithCurrentVersion(context) || !areChannelsAvailable(context);
-    }
-
-    /**
-     * Checks if there are any available tuner channels.
-     */
-    @UiThread
-    public static boolean areChannelsAvailable(Context context) {
-        ChannelDataManager manager = TvApplication.getSingletons(context).getChannelDataManager();
-        if (manager.isDbLoadFinished()) {
-            return manager.getChannelCount() != 0;
-        }
-        // This method should block the UI thread.
-        ContentResolver resolver = context.getContentResolver();
-        try (Cursor c = resolver.query(Channels.CONTENT_URI, new String[] {Channels._ID}, null,
-                null, null)) {
-            return c != null && c.getCount() != 0;
-        }
-    }
-
-    /**
-     * Checks if there are any available TV inputs.
-     */
-    public static boolean areInputsAvailable(Context context) {
-        return TvApplication.getSingletons(context).getTvInputManagerHelper()
-                .getTvInputInfos(true, false).size() > 0;
-    }
-
-    /**
      * Returns merchant collection URL.
      */
     private static String getMerchantCollectionUrl() {
         return "TODO: add a merchant collection url";
     }
+
+    private OnboardingUtils() {}
 }
diff --git a/src/com/android/tv/util/Partner.java b/src/com/android/tv/util/Partner.java
new file mode 100644
index 0000000..e368839
--- /dev/null
+++ b/src/com/android/tv/util/Partner.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.media.tv.TvInputInfo;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This file refers to Partner.java in LeanbackLauncher. Interact with partner customizations. There
+ * can only be one set of customizations on a device, and it must be bundled with the system.
+ */
+public class Partner {
+    private static final String TAG = "Partner";
+    /** Marker action used to discover partner */
+    private static final String ACTION_PARTNER_CUSTOMIZATION =
+            "com.google.android.leanbacklauncher.action.PARTNER_CUSTOMIZATION";
+
+    /** ID tags for device input types */
+    public static final String INPUT_TYPE_BUNDLED_TUNER = "input_type_combined_tuners";
+    public static final String INPUT_TYPE_TUNER = "input_type_tuner";
+    public static final String INPUT_TYPE_CEC_LOGICAL = "input_type_cec_logical";
+    public static final String INPUT_TYPE_CEC_RECORDER = "input_type_cec_recorder";
+    public static final String INPUT_TYPE_CEC_PLAYBACK = "input_type_cec_playback";
+    public static final String INPUT_TYPE_MHL_MOBILE = "input_type_mhl_mobile";
+    public static final String INPUT_TYPE_HDMI = "input_type_hdmi";
+    public static final String INPUT_TYPE_DVI = "input_type_dvi";
+    public static final String INPUT_TYPE_COMPONENT = "input_type_component";
+    public static final String INPUT_TYPE_SVIDEO = "input_type_svideo";
+    public static final String INPUT_TYPE_COMPOSITE = "input_type_composite";
+    public static final String INPUT_TYPE_DISPLAY_PORT = "input_type_displayport";
+    public static final String INPUT_TYPE_VGA = "input_type_vga";
+    public static final String INPUT_TYPE_SCART = "input_type_scart";
+    public static final String INPUT_TYPE_OTHER = "input_type_other";
+
+    private static final String INPUTS_ORDER = "home_screen_inputs_ordering";
+    private static final String TYPE_ARRAY = "array";
+
+    private static Partner sPartner;
+    private static final Object sLock = new Object();
+
+    private final String mPackageName;
+    private final String mReceiverName;
+    private final Resources mResources;
+
+    private static final Map<String, Integer> INPUT_TYPE_MAP = new HashMap<>();
+    static {
+        INPUT_TYPE_MAP.put(INPUT_TYPE_BUNDLED_TUNER, TvInputManagerHelper.TYPE_BUNDLED_TUNER);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_TUNER, TvInputInfo.TYPE_TUNER);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_CEC_LOGICAL, TvInputManagerHelper.TYPE_CEC_DEVICE);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_CEC_RECORDER, TvInputManagerHelper.TYPE_CEC_DEVICE_RECORDER);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_CEC_PLAYBACK, TvInputManagerHelper.TYPE_CEC_DEVICE_PLAYBACK);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_MHL_MOBILE, TvInputManagerHelper.TYPE_MHL_MOBILE);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_HDMI, TvInputInfo.TYPE_HDMI);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_DVI, TvInputInfo.TYPE_DVI);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_COMPONENT, TvInputInfo.TYPE_COMPONENT);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_SVIDEO, TvInputInfo.TYPE_SVIDEO);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_COMPOSITE, TvInputInfo.TYPE_COMPOSITE);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_DISPLAY_PORT, TvInputInfo.TYPE_DISPLAY_PORT);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_VGA, TvInputInfo.TYPE_VGA);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_SCART, TvInputInfo.TYPE_SCART);
+        INPUT_TYPE_MAP.put(INPUT_TYPE_OTHER, TvInputInfo.TYPE_OTHER);
+    }
+
+    private Partner(String packageName, String receiverName, Resources res) {
+        mPackageName = packageName;
+        mReceiverName = receiverName;
+        mResources = res;
+    }
+
+    /** Returns partner instance. */
+    public static Partner getInstance(Context context) {
+        PackageManager pm = context.getPackageManager();
+        synchronized (sLock) {
+            ResolveInfo info = getPartnerResolveInfo(pm);
+            if (info != null) {
+                final String packageName = info.activityInfo.packageName;
+                final String receiverName = info.activityInfo.name;
+                try {
+                    final Resources res = pm.getResourcesForApplication(packageName);
+                    sPartner = new Partner(packageName, receiverName, res);
+                    sPartner.sendInitBroadcast(context);
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.w(TAG, "Failed to find resources for " + packageName);
+                }
+            }
+            if (sPartner == null) {
+                sPartner = new Partner(null, null, null);
+            }
+        }
+        return sPartner;
+    }
+
+    /** Resets the Partner instance to handle the partner package has changed. */
+    public static void reset(Context context, String packageName) {
+        synchronized (sLock) {
+            if (sPartner != null && !TextUtils.isEmpty(packageName)) {
+                if (packageName.equals(sPartner.mPackageName)) {
+                    // Force a refresh, so we send an Init to the updated package
+                    sPartner = null;
+                    getInstance(context);
+                }
+            }
+        }
+    }
+
+    /** This method is used to send init broadcast to the new/changed partner package. */
+    private void sendInitBroadcast(Context context) {
+        if (!TextUtils.isEmpty(mPackageName) && !TextUtils.isEmpty(mReceiverName)) {
+            Intent intent = new Intent(ACTION_PARTNER_CUSTOMIZATION);
+            final ComponentName componentName = new ComponentName(mPackageName, mReceiverName);
+            intent.setComponent(componentName);
+            intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+            context.sendBroadcast(intent);
+        }
+    }
+
+    /** Returns the order of inputs. */
+    public Map<Integer, Integer> getInputsOrderMap() {
+        HashMap<Integer, Integer> map = new HashMap<>();
+        if (mResources != null && !TextUtils.isEmpty(mPackageName)) {
+            String[] inputsArray = null;
+            final int resId = mResources.getIdentifier(INPUTS_ORDER, TYPE_ARRAY, mPackageName);
+            if (resId != 0) {
+                inputsArray = mResources.getStringArray(resId);
+            }
+            if (inputsArray != null) {
+                int priority = 0;
+                for (String input : inputsArray) {
+                    Integer type = INPUT_TYPE_MAP.get(input);
+                    if (type != null) {
+                        map.put(type, priority++);
+                    }
+                }
+            }
+        }
+        return map;
+    }
+
+    private static ResolveInfo getPartnerResolveInfo(PackageManager pm) {
+        final Intent intent = new Intent(ACTION_PARTNER_CUSTOMIZATION);
+        ResolveInfo partnerInfo = null;
+        for (ResolveInfo info : pm.queryBroadcastReceivers(intent, 0)) {
+            if (isSystemApp(info)) {
+                partnerInfo = info;
+                break;
+            }
+        }
+        return partnerInfo;
+    }
+
+    protected static boolean isSystemApp(ResolveInfo info) {
+        return (info.activityInfo != null
+                && info.activityInfo.applicationInfo != null
+                && (info.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
+    }
+}
diff --git a/src/com/android/tv/util/PermissionUtils.java b/src/com/android/tv/util/PermissionUtils.java
index 453885a..a355be9 100644
--- a/src/com/android/tv/util/PermissionUtils.java
+++ b/src/com/android/tv/util/PermissionUtils.java
@@ -47,4 +47,9 @@
         return context.checkSelfPermission(PERMISSION_READ_TV_LISTINGS)
                 == PackageManager.PERMISSION_GRANTED;
     }
+
+    public static boolean hasInternet(Context context) {
+        return context.checkSelfPermission("android.permission.INTERNET")
+                == PackageManager.PERMISSION_GRANTED;
+    }
 }
diff --git a/src/com/android/tv/util/PipInputManager.java b/src/com/android/tv/util/PipInputManager.java
deleted file mode 100644
index 2c51d5a..0000000
--- a/src/com/android/tv/util/PipInputManager.java
+++ /dev/null
@@ -1,432 +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.util;
-
-import android.content.Context;
-import android.media.tv.TvInputInfo;
-import android.media.tv.TvInputManager;
-import android.media.tv.TvInputManager.TvInputCallback;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.tv.ChannelTuner;
-import com.android.tv.R;
-import com.android.tv.data.Channel;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A class that manages inputs for PIP. All tuner inputs are represented to one tuner input for PIP.
- * Hidden inputs should not be visible to the users.
- */
-public class PipInputManager {
-    private static final String TAG = "PipInputManager";
-
-    // Tuner inputs aren't distinguished each other in PipInput. They are handled as one input.
-    // Therefore, we define a fake input id for the unified input.
-    private static final String TUNER_INPUT_ID = "tuner_input_id";
-
-    private final Context mContext;
-    private final TvInputManagerHelper mInputManager;
-    private final ChannelTuner mChannelTuner;
-    private boolean mStarted;
-    private final Map<String, PipInput> mPipInputMap = new HashMap<>();  // inputId -> PipInput
-    private final Set<Listener> mListeners = new ArraySet<>();
-
-    private final TvInputCallback mTvInputCallback = new TvInputCallback() {
-        @Override
-        public void onInputAdded(String inputId) {
-            TvInputInfo input = mInputManager.getTvInputInfo(inputId);
-            if (input.isPassthroughInput()) {
-                boolean available = mInputManager.getInputState(input)
-                        == TvInputManager.INPUT_STATE_CONNECTED;
-                mPipInputMap.put(inputId, new PipInput(inputId, available));
-            } else if (!mPipInputMap.containsKey(TUNER_INPUT_ID)) {
-                boolean available = mChannelTuner.getBrowsableChannelCount() != 0;
-                mPipInputMap.put(TUNER_INPUT_ID, new PipInput(TUNER_INPUT_ID, available));
-            } else {
-                return;
-            }
-            for (Listener l : mListeners) {
-                l.onPipInputListUpdated();
-            }
-        }
-
-        @Override
-        public void onInputRemoved(String inputId) {
-            PipInput pipInput = mPipInputMap.remove(inputId);
-            if (pipInput == null) {
-                if (!mPipInputMap.containsKey(TUNER_INPUT_ID)) {
-                    Log.w(TAG, "A TV input (" + inputId + ") isn't tracked in PipInputManager");
-                    return;
-                }
-                if (mInputManager.getTunerTvInputSize() > 0) {
-                    return;
-                }
-                mPipInputMap.remove(TUNER_INPUT_ID);
-            }
-            for (Listener l : mListeners) {
-                l.onPipInputListUpdated();
-            }
-        }
-
-        @Override
-        public void onInputStateChanged(String inputId, int state) {
-            PipInput pipInput = mPipInputMap.get(inputId);
-            if (pipInput == null) {
-                // For tuner input, state change is handled in mChannelTunerListener.
-                return;
-            }
-            pipInput.updateAvailability();
-        }
-    };
-
-    private final ChannelTuner.Listener mChannelTunerListener = new ChannelTuner.Listener() {
-        @Override
-        public void onLoadFinished() { }
-
-        @Override
-        public void onCurrentChannelUnavailable(Channel channel) { }
-
-        @Override
-        public void onBrowsableChannelListChanged() {
-            PipInput tunerInput = mPipInputMap.get(TUNER_INPUT_ID);
-            if (tunerInput == null) {
-                return;
-            }
-            tunerInput.updateAvailability();
-        }
-
-        @Override
-        public void onChannelChanged(Channel previousChannel, Channel currentChannel) {
-            if (previousChannel != null && currentChannel != null
-                    && !previousChannel.isPassthrough() && !currentChannel.isPassthrough()) {
-                // Channel change between channels for tuner inputs.
-                return;
-            }
-            PipInput previousMainInput = getPipInput(previousChannel);
-            if (previousMainInput != null) {
-                previousMainInput.updateAvailability();
-            }
-            PipInput currentMainInput = getPipInput(currentChannel);
-            if (currentMainInput != null) {
-                currentMainInput.updateAvailability();
-            }
-        }
-    };
-
-    public PipInputManager(Context context, TvInputManagerHelper inputManager,
-            ChannelTuner channelTuner) {
-        mContext = context;
-        mInputManager = inputManager;
-        mChannelTuner = channelTuner;
-    }
-
-    /**
-     * Starts {@link PipInputManager}.
-     */
-    public void start() {
-        if (mStarted) {
-            return;
-        }
-        mStarted = true;
-        mInputManager.addCallback(mTvInputCallback);
-        mChannelTuner.addListener(mChannelTunerListener);
-        initializePipInputList();
-    }
-
-    /**
-     * Stops {@link PipInputManager}.
-     */
-    public void stop() {
-        if (!mStarted) {
-            return;
-        }
-        mStarted = false;
-        mInputManager.removeCallback(mTvInputCallback);
-        mChannelTuner.removeListener(mChannelTunerListener);
-        mPipInputMap.clear();
-    }
-
-    /**
-     * Adds a {@link PipInputManager.Listener}.
-     */
-    public void addListener(Listener listener) {
-        mListeners.add(listener);
-    }
-
-    /**
-     * Removes a {@link PipInputManager.Listener}.
-     */
-    public void removeListener(Listener listener) {
-        mListeners.remove(listener);
-    }
-
-    /**
-     * Gets the size of inputs for PIP.
-     *
-     * <p>The hidden inputs are not counted.
-     *
-     * @param availableOnly If {@code true}, it counts only available PIP inputs. Please see {@link
-     *        PipInput#isAvailable()} for the details of availability.
-     */
-    public int getPipInputSize(boolean availableOnly) {
-        int count = 0;
-        for (PipInput pipInput : mPipInputMap.values()) {
-            if (!pipInput.isHidden() && (!availableOnly || pipInput.mAvailable)) {
-                ++count;
-            }
-            if (pipInput.isPassthrough()) {
-                TvInputInfo info = pipInput.getInputInfo();
-                // Do not count HDMI ports if a CEC device is directly connected to the port.
-                if (info.getParentId() != null && !info.isConnectedToHdmiSwitch()) {
-                    --count;
-                }
-            }
-        }
-        return count;
-    }
-
-    /**
-     * Gets the list of inputs for PIP..
-     *
-     * <p>The hidden inputs are excluded.
-     *
-     * @param availableOnly If true, it returns only available PIP inputs. Please see {@link
-     *        PipInput#isAvailable()} for the details of availability.
-     */
-    public List<PipInput> getPipInputList(boolean availableOnly) {
-        List<PipInput> pipInputs = new ArrayList<>();
-        List<PipInput> removeInputs = new ArrayList<>();
-        for (PipInput pipInput : mPipInputMap.values()) {
-            if (!pipInput.isHidden() && (!availableOnly || pipInput.mAvailable)) {
-                pipInputs.add(pipInput);
-            }
-            if (pipInput.isPassthrough()) {
-                TvInputInfo info = pipInput.getInputInfo();
-                // Do not show HDMI ports if a CEC device is directly connected to the port.
-                if (info.getParentId() != null && !info.isConnectedToHdmiSwitch()) {
-                    removeInputs.add(mPipInputMap.get(info.getParentId()));
-                }
-            }
-        }
-        if (!removeInputs.isEmpty()) {
-            pipInputs.removeAll(removeInputs);
-        }
-        Collections.sort(pipInputs, new Comparator<PipInput>() {
-            @Override
-            public int compare(PipInput lhs, PipInput rhs) {
-                if (!lhs.mIsPassthrough) {
-                    return -1;
-                }
-                if (!rhs.mIsPassthrough) {
-                    return 1;
-                }
-                String a = lhs.getLabel();
-                String b = rhs.getLabel();
-                return a.compareTo(b);
-            }
-        });
-        return pipInputs;
-    }
-
-    /**
-     * Returns an PIP input corresponding to {@code channel}.
-     */
-    public PipInput getPipInput(Channel channel) {
-        if (channel == null) {
-            return null;
-        }
-        if (channel.isPassthrough()) {
-            return mPipInputMap.get(channel.getInputId());
-        } else {
-            return mPipInputMap.get(TUNER_INPUT_ID);
-        }
-    }
-
-    /**
-     * Returns true, if {@code channel1} and {@code channel2} belong to the same input. For example,
-     * two channels from different tuner inputs are also in the same input "Tuner" from PIP
-     * point of view.
-     */
-    public boolean areInSamePipInput(Channel channel1, Channel channel2) {
-        PipInput input1 = getPipInput(channel1);
-        PipInput input2 = getPipInput(channel2);
-        return input1 != null && input2 != null
-                && getPipInput(channel1).equals(getPipInput(channel2));
-    }
-
-    private void initializePipInputList() {
-        boolean hasTunerInput = false;
-        for (TvInputInfo input : mInputManager.getTvInputInfos(false, false)) {
-            if (input.isPassthroughInput()) {
-                boolean available = mInputManager.getInputState(input)
-                        == TvInputManager.INPUT_STATE_CONNECTED;
-                mPipInputMap.put(input.getId(), new PipInput(input.getId(), available));
-            } else if (!hasTunerInput) {
-                hasTunerInput = true;
-                boolean available = mChannelTuner.getBrowsableChannelCount() != 0;
-                mPipInputMap.put(TUNER_INPUT_ID, new PipInput(TUNER_INPUT_ID, available));
-            }
-        }
-        PipInput input = getPipInput(mChannelTuner.getCurrentChannel());
-        if (input != null) {
-            input.updateAvailability();
-        }
-        for (Listener l : mListeners) {
-            l.onPipInputListUpdated();
-        }
-    }
-
-    /**
-     * Listeners to notify PIP input state changes.
-     */
-    public interface Listener {
-        /**
-         * Called when the state (availability) of PIP inputs is changed.
-         */
-        void onPipInputStateUpdated();
-
-        /**
-         * Called when the list of PIP inputs is changed.
-         */
-        void onPipInputListUpdated();
-    }
-
-    /**
-     * Input class for PIP. It has useful methods for PIP handling.
-     */
-    public class PipInput {
-        private final String mInputId;
-        private final boolean mIsPassthrough;
-        private final TvInputInfo mInputInfo;
-        private boolean mAvailable;
-
-        private PipInput(String inputId, boolean available) {
-            mInputId = inputId;
-            mIsPassthrough = !mInputId.equals(TUNER_INPUT_ID);
-            if (mIsPassthrough) {
-                mInputInfo = mInputManager.getTvInputInfo(mInputId);
-            } else {
-                mInputInfo = null;
-            }
-            mAvailable = available;
-        }
-
-        /**
-         * Returns the {@link TvInputInfo} object that matches to this PIP input.
-         */
-        public TvInputInfo getInputInfo() {
-            return mInputInfo;
-        }
-
-        /**
-         * Returns {@code true}, if the input is available for PIP. If a channel of an input is
-         * already played or an input is not connected state or there is no browsable channel, the
-         * input is unavailable.
-         */
-        public boolean isAvailable() {
-            return mAvailable;
-        }
-
-        /**
-         * Returns true, if the input is a passthrough TV input.
-         */
-        public boolean isPassthrough() {
-            return mIsPassthrough;
-        }
-
-        /**
-         * Gets a channel to play in a PIP view.
-         */
-        public Channel getChannel() {
-            if (mIsPassthrough) {
-                return Channel.createPassthroughChannel(mInputId);
-            } else {
-                return mChannelTuner.findNearestBrowsableChannel(
-                        Utils.getLastWatchedChannelId(mContext));
-            }
-        }
-
-        /**
-         * Gets a label of the input.
-         */
-        public String getLabel() {
-            if (mIsPassthrough) {
-                return mInputInfo.loadLabel(mContext).toString();
-            } else {
-                return mContext.getString(R.string.input_selector_tuner_label);
-            }
-        }
-
-        /**
-         * Gets a long label including a customized label.
-         */
-        public String getLongLabel() {
-            if (mIsPassthrough) {
-                String customizedLabel = Utils.loadLabel(mContext, mInputInfo);
-                String label = getLabel();
-                if (label.equals(customizedLabel)) {
-                    return customizedLabel;
-                }
-                return customizedLabel + " (" + label + ")";
-            } else {
-                return mContext.getString(R.string.input_long_label_for_tuner);
-            }
-        }
-
-        /**
-         * Updates availability. It returns true, if availability is changed.
-         */
-        private void updateAvailability() {
-            boolean available;
-            // current playing input cannot be available for PIP.
-            Channel currentChannel = mChannelTuner.getCurrentChannel();
-            if (mIsPassthrough) {
-                if (currentChannel != null && currentChannel.getInputId().equals(mInputId)) {
-                    available = false;
-                } else {
-                    available = mInputManager.getInputState(mInputId)
-                            == TvInputManager.INPUT_STATE_CONNECTED;
-                }
-            } else {
-                if (currentChannel != null && !currentChannel.isPassthrough()) {
-                    available = false;
-                } else {
-                    available = mChannelTuner.getBrowsableChannelCount() > 0;
-                }
-            }
-            if (mAvailable != available) {
-                mAvailable = available;
-                for (Listener l : mListeners) {
-                    l.onPipInputStateUpdated();
-                }
-            }
-        }
-
-        private boolean isHidden() {
-            // mInputInfo is null for the tuner input and it's always visible.
-            return mInputInfo != null && mInputInfo.isHidden(mContext);
-        }
-    }
-}
diff --git a/src/com/android/tv/util/RecurringRunner.java b/src/com/android/tv/util/RecurringRunner.java
index 4135bd4..8b45131 100644
--- a/src/com/android/tv/util/RecurringRunner.java
+++ b/src/com/android/tv/util/RecurringRunner.java
@@ -57,12 +57,15 @@
         mHandler = new Handler(mContext.getMainLooper());
     }
 
-    public void start() {
+    public void start(boolean resetNextRunTime) {
         SoftPreconditions.checkState(!mRunning, TAG, mName + " start is called twice.");
         if (mRunning) {
             return;
         }
         mRunning = true;
+        if (resetNextRunTime) {
+            resetNextRunTime();
+        }
         new AsyncTask<Void, Void, Long>() {
             @Override
             protected Long doInBackground(Void... params) {
@@ -76,6 +79,10 @@
         }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
     }
 
+    public void start() {
+        start(false);
+    }
+
     public void stop() {
         mRunning = false;
         mHandler.removeCallbacksAndMessages(null);
diff --git a/src/com/android/tv/util/SearchManagerHelper.java b/src/com/android/tv/util/SearchManagerHelper.java
deleted file mode 100644
index b6e34d7..0000000
--- a/src/com/android/tv/util/SearchManagerHelper.java
+++ /dev/null
@@ -1,61 +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.util;
-
-import android.app.SearchManager;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.util.Log;
-
-import java.lang.reflect.InvocationTargetException;
-
-/**
- * A convenience class for calling methods in android.app.SearchManager.
- */
-public final class SearchManagerHelper {
-    private static final String TAG = "SearchManagerHelper";
-
-    private static final Object sLock = new Object();
-    private static SearchManagerHelper sInstance;
-
-    private final SearchManager mSearchManager;
-
-    private SearchManagerHelper(Context context) {
-        mSearchManager = ((android.app.SearchManager) context.getSystemService(
-                Context.SEARCH_SERVICE));
-    }
-
-    public static SearchManagerHelper getInstance(Context context) {
-        synchronized (sLock) {
-            if (sInstance == null) {
-                sInstance = new SearchManagerHelper(context.getApplicationContext());
-            }
-            return sInstance;
-        }
-    }
-
-    public void launchAssistAction() {
-        try {
-            SearchManager.class.getDeclaredMethod("launchLegacyAssist", String.class, Integer.TYPE,
-                    Bundle.class).invoke(mSearchManager, null, UserHandle.myUserId(), null);
-        }  catch (NoSuchMethodException | IllegalArgumentException | IllegalAccessException
-                | InvocationTargetException e) {
-            Log.e(TAG, "Fail to call SearchManager.launchAssistAction", e);
-        }
-    }
-}
diff --git a/src/com/android/tv/util/SetupUtils.java b/src/com/android/tv/util/SetupUtils.java
index 8223a81..32e3a81 100644
--- a/src/com/android/tv/util/SetupUtils.java
+++ b/src/com/android/tv/util/SetupUtils.java
@@ -37,8 +37,6 @@
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.data.ChannelDataManager;
-import com.android.tv.data.epg.EpgFetcher;
-import com.android.tv.experiments.Experiments;
 import com.android.tv.tuner.tvinput.TunerTvInputService;
 
 import java.util.Collections;
@@ -114,7 +112,7 @@
                 @Override
                 public void onLoadFinished() {
                     manager.removeListener(this);
-                    updateChannelBrowsable(mTvApplication, inputId, postRunnable);
+                    updateChannelsAfterSetup(mTvApplication, inputId, postRunnable);
                 }
 
                 @Override
@@ -124,17 +122,18 @@
                 public void onChannelBrowsableChanged() { }
             });
         } else {
-            updateChannelBrowsable(mTvApplication, inputId, postRunnable);
+            updateChannelsAfterSetup(mTvApplication, inputId, postRunnable);
         }
     }
 
-    private static void updateChannelBrowsable(Context context, final String inputId,
+    private static void updateChannelsAfterSetup(Context context, final String inputId,
             final Runnable postRunnable) {
         ApplicationSingletons appSingletons = TvApplication.getSingletons(context);
         final ChannelDataManager manager = appSingletons.getChannelDataManager();
         manager.updateChannels(new Runnable() {
             @Override
             public void run() {
+                Channel firstChannelForInput = null;
                 boolean browsableChanged = false;
                 for (Channel channel : manager.getChannelList()) {
                     if (channel.getInputId().equals(inputId)) {
@@ -142,8 +141,14 @@
                             manager.updateBrowsable(channel.getId(), true, true);
                             browsableChanged = true;
                         }
+                        if (firstChannelForInput == null) {
+                            firstChannelForInput = channel;
+                        }
                     }
                 }
+                if (firstChannelForInput != null) {
+                    Utils.setLastWatchedChannel(context, firstChannelForInput);
+                }
                 if (browsableChanged) {
                     manager.notifyChannelBrowsableChanged();
                     manager.applyUpdatedValuesToDb();
@@ -382,13 +387,5 @@
             mSetUpInputs.add(inputId);
             mSharedPreferences.edit().putStringSet(PREF_KEY_SET_UP_INPUTS, mSetUpInputs).apply();
         }
-        // Start fetching program guide data for internal tuners.
-        Context context = mTvApplication.getApplicationContext();
-        if (Utils.isInternalTvInput(context, inputId)) {
-            if (context.checkSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
-                    == PackageManager.PERMISSION_GRANTED && Experiments.CLOUD_EPG.get()) {
-                EpgFetcher.getInstance(context).startImmediately();
-            }
-        }
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/tuner/util/StringUtils.java b/src/com/android/tv/util/StringUtils.java
similarity index 96%
rename from src/com/android/tv/tuner/util/StringUtils.java
rename to src/com/android/tv/util/StringUtils.java
index 15571e7..659807e 100644
--- a/src/com/android/tv/tuner/util/StringUtils.java
+++ b/src/com/android/tv/util/StringUtils.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.tv.tuner.util;
+package com.android.tv.util;
 
 /**
  * Utility class for handling {@link String}.
diff --git a/src/com/android/tv/util/TimeShiftUtils.java b/src/com/android/tv/util/TimeShiftUtils.java
index 238d0e7..8038a78 100644
--- a/src/com/android/tv/util/TimeShiftUtils.java
+++ b/src/com/android/tv/util/TimeShiftUtils.java
@@ -18,7 +18,6 @@
 
 import java.util.concurrent.TimeUnit;
 
-// TODO: move related functions in TimeShiftManger here.
 /**
  * A class that includes convenience methods for time shift plays.
  */
@@ -40,7 +39,7 @@
      * Returns real speeds used in time shift play. This method is only for fast-forwarding and
      * rewinding. The normal play speed is not addressed here.
      *
-     * @param speedLevel the valid value is ranged from 0 to {@link MAX_SPPED_LEVEL}.
+     * @param speedLevel the valid value is ranged from 0 to {@link #MAX_SPEED_LEVEL}.
      * @param programDurationMillis the length of program under playing.
      * @throws IndexOutOfBoundsException if speed level is out of its range.
      */
@@ -60,4 +59,3 @@
                 : SHORT_PROGRAM_SPEED_FACTORS[MAX_SPEED_LEVEL];
     }
 }
-
diff --git a/src/com/android/tv/util/TvInputManagerHelper.java b/src/com/android/tv/util/TvInputManagerHelper.java
index 121f56e..730a985 100644
--- a/src/com/android/tv/util/TvInputManagerHelper.java
+++ b/src/com/android/tv/util/TvInputManagerHelper.java
@@ -18,20 +18,26 @@
 
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.hardware.hdmi.HdmiDeviceInfo;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
 import android.media.tv.TvInputManager.TvInputCallback;
 import android.os.Handler;
 import android.support.annotation.VisibleForTesting;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 import android.util.Log;
 
 import com.android.tv.Features;
 import com.android.tv.common.SoftPreconditions;
+import com.android.tv.common.TvCommonUtils;
 import com.android.tv.parental.ContentRatingsManager;
 import com.android.tv.parental.ParentalControlSettings;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -42,14 +48,64 @@
 public class TvInputManagerHelper {
     private static final String TAG = "TvInputManagerHelper";
     private static final boolean DEBUG = false;
+
+    /**
+     * Types of HDMI device and bundled tuner.
+     */
+    public static final int TYPE_CEC_DEVICE = -2;
+    public static final int TYPE_BUNDLED_TUNER = -3;
+    public static final int TYPE_CEC_DEVICE_RECORDER = -4;
+    public static final int TYPE_CEC_DEVICE_PLAYBACK = -5;
+    public static final int TYPE_MHL_MOBILE = -6;
+
+    private static final String PERMISSION_ACCESS_ALL_EPG_DATA =
+            "com.android.providers.tv.permission.ACCESS_ALL_EPG_DATA";
+    private static final String [] mPhysicalTunerBlackList = {
+    };
+    private static final String META_LABEL_SORT_KEY = "input_sort_key";
+
+    /**
+     * The default tv input priority to show.
+     */
+    private static final ArrayList<Integer> DEFAULT_TV_INPUT_PRIORITY = new ArrayList<>();
+    static {
+        DEFAULT_TV_INPUT_PRIORITY.add(TYPE_BUNDLED_TUNER);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_TUNER);
+        DEFAULT_TV_INPUT_PRIORITY.add(TYPE_CEC_DEVICE);
+        DEFAULT_TV_INPUT_PRIORITY.add(TYPE_CEC_DEVICE_RECORDER);
+        DEFAULT_TV_INPUT_PRIORITY.add(TYPE_CEC_DEVICE_PLAYBACK);
+        DEFAULT_TV_INPUT_PRIORITY.add(TYPE_MHL_MOBILE);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_HDMI);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_DVI);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_COMPONENT);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_SVIDEO);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_COMPOSITE);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_DISPLAY_PORT);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_VGA);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_SCART);
+        DEFAULT_TV_INPUT_PRIORITY.add(TvInputInfo.TYPE_OTHER);
+    }
+
     private static final String[] PARTNER_TUNER_INPUT_PREFIX_BLACKLIST = {
     };
 
+    private static final String[] TESTABLE_INPUTS = {
+            "com.android.tv.testinput/.TestTvInputService"
+    };
+
     private final Context mContext;
+    private final PackageManager mPackageManager;
     private final TvInputManager mTvInputManager;
     private final Map<String, Integer> mInputStateMap = new HashMap<>();
     private final Map<String, TvInputInfo> mInputMap = new HashMap<>();
+    private final Map<String, String> mTvInputLabels = new ArrayMap<>();
+    private final Map<String, String> mTvInputCustomLabels = new ArrayMap<>();
     private final Map<String, Boolean> mInputIdToPartnerInputMap = new HashMap<>();
+
+    private final Map<String, CharSequence> mTvInputApplicationLabels = new ArrayMap<>();
+    private final Map<String, Drawable> mTvInputApplicationIcons = new ArrayMap<>();
+    private final Map<String, Drawable> mTvInputAppliactionBanners = new ArrayMap<>();
+
     private final TvInputCallback mInternalCallback = new TvInputCallback() {
         @Override
         public void onInputStateChanged(String inputId, int state) {
@@ -72,6 +128,11 @@
             TvInputInfo info = mTvInputManager.getTvInputInfo(inputId);
             if (info != null) {
                 mInputMap.put(inputId, info);
+                mTvInputLabels.put(inputId, info.loadLabel(mContext).toString());
+                CharSequence inputCustomLabel = info.loadCustomLabel(mContext);
+                if (inputCustomLabel != null) {
+                    mTvInputCustomLabels.put(inputId, inputCustomLabel.toString());
+                }
                 mInputStateMap.put(inputId, mTvInputManager.getInputState(inputId));
                 mInputIdToPartnerInputMap.put(inputId, isPartnerInput(info));
             }
@@ -85,6 +146,11 @@
         public void onInputRemoved(String inputId) {
             if (DEBUG) Log.d(TAG, "onInputRemoved " + inputId);
             mInputMap.remove(inputId);
+            mTvInputLabels.remove(inputId);
+            mTvInputCustomLabels.remove(inputId);
+            mTvInputApplicationLabels.remove(inputId);
+            mTvInputApplicationIcons.remove(inputId);
+            mTvInputAppliactionBanners.remove(inputId);
             mInputStateMap.remove(inputId);
             mInputIdToPartnerInputMap.remove(inputId);
             mContentRatingsManager.update();
@@ -103,6 +169,14 @@
             }
             TvInputInfo info = mTvInputManager.getTvInputInfo(inputId);
             mInputMap.put(inputId, info);
+            mTvInputLabels.put(inputId, info.loadLabel(mContext).toString());
+            CharSequence inputCustomLabel = info.loadCustomLabel(mContext);
+            if (inputCustomLabel != null) {
+                mTvInputCustomLabels.put(inputId, inputCustomLabel.toString());
+            }
+            mTvInputApplicationLabels.remove(inputId);
+            mTvInputApplicationIcons.remove(inputId);
+            mTvInputAppliactionBanners.remove(inputId);
             for (TvInputCallback callback : mCallbacks) {
                 callback.onInputUpdated(inputId);
             }
@@ -114,6 +188,11 @@
         public void onTvInputInfoUpdated(TvInputInfo inputInfo) {
             if (DEBUG) Log.d(TAG, "onTvInputInfoUpdated " + inputInfo);
             mInputMap.put(inputInfo.getId(), inputInfo);
+            mTvInputLabels.put(inputInfo.getId(), inputInfo.loadLabel(mContext).toString());
+            CharSequence inputCustomLabel = inputInfo.loadCustomLabel(mContext);
+            if (inputCustomLabel != null) {
+                mTvInputCustomLabels.put(inputInfo.getId(), inputCustomLabel.toString());
+            }
             for (TvInputCallback callback : mCallbacks) {
                 callback.onTvInputInfoUpdated(inputInfo);
             }
@@ -131,13 +210,18 @@
 
     public TvInputManagerHelper(Context context) {
         mContext = context.getApplicationContext();
+        mPackageManager = context.getPackageManager();
         mTvInputManager = (TvInputManager) context.getSystemService(Context.TV_INPUT_SERVICE);
         mContentRatingsManager = new ContentRatingsManager(context);
         mParentalControlSettings = new ParentalControlSettings(context);
-        mTvInputInfoComparator = new TvInputInfoComparator(this);
+        mTvInputInfoComparator = new InputComparatorInternal(this);
     }
 
     public void start() {
+        if (!hasTvInputManager()) {
+            // Not a TV device
+            return;
+        }
         if (mStarted) {
             return;
         }
@@ -145,6 +229,11 @@
         mStarted = true;
         mTvInputManager.registerCallback(mInternalCallback, mHandler);
         mInputMap.clear();
+        mTvInputLabels.clear();
+        mTvInputCustomLabels.clear();
+        mTvInputApplicationLabels.clear();
+        mTvInputApplicationIcons.clear();
+        mTvInputAppliactionBanners.clear();
         mInputStateMap.clear();
         mInputIdToPartnerInputMap.clear();
         for (TvInputInfo input : mTvInputManager.getTvInputList()) {
@@ -171,9 +260,23 @@
         mStarted = false;
         mInputStateMap.clear();
         mInputMap.clear();
+        mTvInputLabels.clear();
+        mTvInputCustomLabels.clear();
+        mTvInputApplicationLabels.clear();
+        mTvInputApplicationIcons.clear();
+        mTvInputAppliactionBanners.clear();;
         mInputIdToPartnerInputMap.clear();
     }
 
+    /**
+     * Clears the TvInput labels map.
+     */
+    public void clearTvInputLabels() {
+        mTvInputLabels.clear();
+        mTvInputCustomLabels.clear();
+        mTvInputApplicationLabels.clear();
+    }
+
     public List<TvInputInfo> getTvInputInfos(boolean availableOnly, boolean tunerOnly) {
         ArrayList<TvInputInfo> list = new ArrayList<>();
         for (Map.Entry<String, Integer> pair : mInputStateMap.entrySet()) {
@@ -192,7 +295,7 @@
 
     /**
      * Returns the default comparator for {@link TvInputInfo}.
-     * See {@link TvInputInfoComparator} for detail.
+     * See {@link InputComparatorInternal} for detail.
      */
     public Comparator<TvInputInfo> getDefaultTvInputInfoComparator() {
         return mTvInputInfoComparator;
@@ -237,15 +340,81 @@
     }
 
     /**
-     * Loads label of {@code info}.
+     * Is (Context.TV_INPUT_SERVICE) available.
      *
-     * It's visible for comparator test to mock TvInputInfo.
-     * Package private is enough for this method, but public is necessary to workaround mockito
-     * bug.
+     * <p>This is only available on TV devices.
      */
-    @VisibleForTesting
+    public boolean hasTvInputManager() {
+        return mTvInputManager != null;
+    }
+
+    /**
+     * Loads label of {@code info}.
+     */
     public String loadLabel(TvInputInfo info) {
-        return info.loadLabel(mContext).toString();
+        String label = mTvInputLabels.get(info.getId());
+        if (label == null) {
+            label = info.loadLabel(mContext).toString();
+            mTvInputLabels.put(info.getId(), label);
+        }
+        return label;
+    }
+
+    /**
+     * Loads custom label of {@code info}
+     */
+    public String loadCustomLabel(TvInputInfo info) {
+        String customLabel = mTvInputCustomLabels.get(info.getId());
+        if (customLabel == null) {
+            CharSequence customLabelCharSequence = info.loadCustomLabel(mContext);
+            if (customLabelCharSequence != null) {
+                customLabel = customLabelCharSequence.toString();
+                mTvInputCustomLabels.put(info.getId(), customLabel);
+            }
+        }
+        return customLabel;
+    }
+
+    /**
+     * Gets the tv input application's label.
+     */
+    public CharSequence getTvInputApplicationLabel(CharSequence inputId) {
+        return mTvInputApplicationLabels.get(inputId);
+    }
+
+    /**
+     * Stores the tv input application's label.
+     */
+    public void setTvInputApplicationLabel(String inputId, CharSequence label) {
+        mTvInputApplicationLabels.put(inputId, label);
+    }
+
+    /**
+     * Gets the tv input application's icon.
+     */
+    public Drawable getTvInputApplicationIcon(String inputId) {
+        return mTvInputApplicationIcons.get(inputId);
+    }
+
+    /**
+     * Stores the tv input application's icon.
+     */
+    public void setTvInputApplicationIcon(String inputId, Drawable icon) {
+        mTvInputApplicationIcons.put(inputId, icon);
+    }
+
+    /**
+     * Gets the tv input application's banner.
+     */
+    public Drawable getTvInputApplicationBanner(String inputId) {
+        return mTvInputAppliactionBanners.get(inputId);
+    }
+
+    /**
+     * Stores the tv input application's banner.
+     */
+    public void setTvInputApplicationBanner(String inputId, Drawable banner) {
+        mTvInputAppliactionBanners.put(inputId, banner);
     }
 
     /**
@@ -321,15 +490,55 @@
         return mContentRatingsManager;
     }
 
-    private boolean isInBlackList(String inputId) {
-        if (!Features.USE_PARTNER_INPUT_BLACKLIST.isEnabled(mContext)) {
+    private int getInputSortKey(TvInputInfo input) {
+        return input.getServiceInfo().metaData.getInt(META_LABEL_SORT_KEY,
+                Integer.MAX_VALUE);
+    }
+
+    private boolean isInputPhysicalTuner(TvInputInfo input) {
+        String packageName = input.getServiceInfo().packageName;
+        if (Arrays.asList(mPhysicalTunerBlackList).contains(packageName)) {
             return false;
         }
-        for (String disabledTunerInputPrefix : PARTNER_TUNER_INPUT_PREFIX_BLACKLIST) {
-            if (inputId.contains(disabledTunerInputPrefix)) {
-                return true;
+
+        if (input.createSetupIntent() == null) {
+            return false;
+        } else {
+            boolean mayBeTunerInput = mPackageManager.checkPermission(
+                    PERMISSION_ACCESS_ALL_EPG_DATA, input.getServiceInfo().packageName)
+                    == PackageManager.PERMISSION_GRANTED;
+            if (!mayBeTunerInput) {
+                try {
+                    ApplicationInfo ai = mPackageManager.getApplicationInfo(
+                            input.getServiceInfo().packageName, 0);
+                    if ((ai.flags & (ApplicationInfo.FLAG_SYSTEM
+                            | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) == 0) {
+                        return false;
+                    }
+                } catch (PackageManager.NameNotFoundException e) {
+                    return false;
+                }
             }
         }
+        return true;
+    }
+
+    private boolean isInBlackList(String inputId) {
+        if (Features.USE_PARTNER_INPUT_BLACKLIST.isEnabled(mContext)) {
+            for (String disabledTunerInputPrefix : PARTNER_TUNER_INPUT_PREFIX_BLACKLIST) {
+                if (inputId.contains(disabledTunerInputPrefix)) {
+                    return true;
+                }
+            }
+        }
+        if (TvCommonUtils.isRunningInTest()) {
+            for (String testableInput : TESTABLE_INPUTS) {
+                if (testableInput.equals(inputId)) {
+                    return false;
+                }
+            }
+            return true;
+        }
         return false;
     }
 
@@ -342,10 +551,10 @@
      * (i.e. Mockito's spy doesn't work)
      */
     @VisibleForTesting
-    static class TvInputInfoComparator implements Comparator<TvInputInfo> {
+    static class InputComparatorInternal implements Comparator<TvInputInfo> {
         private final TvInputManagerHelper mInputManager;
 
-        public TvInputInfoComparator(TvInputManagerHelper inputManager) {
+        public InputComparatorInternal(TvInputManagerHelper inputManager) {
             mInputManager = inputManager;
         }
 
@@ -357,4 +566,123 @@
             return mInputManager.loadLabel(lhs).compareTo(mInputManager.loadLabel(rhs));
         }
     }
+
+    /**
+     * A comparator used for {@link com.android.tv.ui.SelectInputView} to show the list of
+     * TV inputs.
+     */
+    public static class HardwareInputComparator implements Comparator<TvInputInfo> {
+        private Map<Integer, Integer> mTypePriorities = new HashMap<>();
+        private final TvInputManagerHelper mTvInputManagerHelper;
+        private final Context mContext;
+
+        public HardwareInputComparator(Context context, TvInputManagerHelper tvInputManagerHelper) {
+            mContext = context;
+            mTvInputManagerHelper = tvInputManagerHelper;
+            setupDeviceTypePriorities();
+        }
+
+        @Override
+        public int compare(TvInputInfo lhs, TvInputInfo rhs) {
+            if (lhs == null) {
+                return (rhs == null) ? 0 : 1;
+            }
+            if (rhs == null) {
+                return -1;
+            }
+
+            boolean enabledL = (mTvInputManagerHelper.getInputState(lhs)
+                    != TvInputManager.INPUT_STATE_DISCONNECTED);
+            boolean enabledR = (mTvInputManagerHelper.getInputState(rhs)
+                    != TvInputManager.INPUT_STATE_DISCONNECTED);
+            if (enabledL != enabledR) {
+                return enabledL ? -1 : 1;
+            }
+
+            int priorityL = getPriority(lhs);
+            int priorityR = getPriority(rhs);
+            if (priorityL != priorityR) {
+                return priorityL - priorityR;
+            }
+
+            if (lhs.getType() == TvInputInfo.TYPE_TUNER
+                    && rhs.getType() == TvInputInfo.TYPE_TUNER) {
+                boolean isPhysicalL = mTvInputManagerHelper.isInputPhysicalTuner(lhs);
+                boolean isPhysicalR = mTvInputManagerHelper.isInputPhysicalTuner(rhs);
+                if (isPhysicalL != isPhysicalR) {
+                    return isPhysicalL ? -1 : 1;
+                }
+            }
+
+            int sortKeyL = mTvInputManagerHelper.getInputSortKey(lhs);
+            int sortKeyR = mTvInputManagerHelper.getInputSortKey(rhs);
+            if (sortKeyL != sortKeyR) {
+                return sortKeyR - sortKeyL;
+            }
+
+            String parentLabelL = lhs.getParentId() != null
+                    ? getLabel(mTvInputManagerHelper.getTvInputInfo(lhs.getParentId()))
+                            : getLabel(mTvInputManagerHelper.getTvInputInfo(lhs.getId()));
+            String parentLabelR = rhs.getParentId() != null
+                    ? getLabel(mTvInputManagerHelper.getTvInputInfo(rhs.getParentId()))
+                            : getLabel(mTvInputManagerHelper.getTvInputInfo(rhs.getId()));
+
+            if (!TextUtils.equals(parentLabelL, parentLabelR)) {
+                return parentLabelL.compareToIgnoreCase(parentLabelR);
+            }
+            return getLabel(lhs).compareToIgnoreCase(getLabel(rhs));
+        }
+
+        private String getLabel(TvInputInfo input) {
+            if (input == null) {
+                return "";
+            }
+            String label = mTvInputManagerHelper.loadCustomLabel(input);
+            if (TextUtils.isEmpty(label)) {
+                label = mTvInputManagerHelper.loadLabel(input);
+            }
+            return label;
+        }
+
+        private int getPriority(TvInputInfo info) {
+            Integer priority = null;
+            if (mTypePriorities != null) {
+                priority = mTypePriorities.get(getTvInputTypeForPriority(info));
+            }
+            if (priority != null) {
+                return priority;
+            }
+            return Integer.MAX_VALUE;
+        }
+
+        private void setupDeviceTypePriorities() {
+            mTypePriorities = Partner.getInstance(mContext).getInputsOrderMap();
+
+            // Fill in any missing priorities in the map we got from the OEM
+            int priority = mTypePriorities.size();
+            for (int type : DEFAULT_TV_INPUT_PRIORITY) {
+                if (!mTypePriorities.containsKey(type)) {
+                    mTypePriorities.put(type, priority++);
+                }
+            }
+        }
+
+        private int getTvInputTypeForPriority(TvInputInfo info) {
+            if (info.getHdmiDeviceInfo() != null) {
+                if (info.getHdmiDeviceInfo().isCecDevice()) {
+                    switch (info.getHdmiDeviceInfo().getDeviceType()) {
+                        case HdmiDeviceInfo.DEVICE_RECORDER:
+                            return TYPE_CEC_DEVICE_RECORDER;
+                        case HdmiDeviceInfo.DEVICE_PLAYBACK:
+                            return TYPE_CEC_DEVICE_PLAYBACK;
+                        default:
+                            return TYPE_CEC_DEVICE;
+                    }
+                } else if (info.getHdmiDeviceInfo().isMhlDevice()) {
+                    return TYPE_MHL_MOBILE;
+                }
+            }
+            return info.getType();
+        }
+    }
 }
diff --git a/src/com/android/tv/util/TvSettings.java b/src/com/android/tv/util/TvSettings.java
index 97ff59d..c5fde31 100644
--- a/src/com/android/tv/util/TvSettings.java
+++ b/src/com/android/tv/util/TvSettings.java
@@ -17,6 +17,8 @@
 package com.android.tv.util;
 
 import android.content.Context;
+import android.content.SharedPreferences;
+import android.media.tv.TvTrackInfo;
 import android.preference.PreferenceManager;
 import android.support.annotation.IntDef;
 
@@ -26,53 +28,27 @@
 import java.util.HashSet;
 import java.util.Set;
 
-
 /**
  * A class about the constants for TV settings.
  * Objects that are returned from the various {@code get} methods must be treated as immutable.
  */
 public final class TvSettings {
-    private TvSettings() {}
-
     public static final String PREF_DISPLAY_MODE = "display_mode";  // int value
-    public static final String PREF_PIP_LAYOUT = "pip_layout"; // int value
-    public static final String PREF_PIP_SIZE = "pip_size";  // int value
     public static final String PREF_PIN = "pin"; // 4-digit string value. Otherwise, it's not set.
 
-    // PIP sounds
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            PIP_SOUND_MAIN, PIP_SOUND_PIP_WINDOW })
-    public @interface PipSound {}
-    public static final int PIP_SOUND_MAIN = 0;
-    public static final int PIP_SOUND_PIP_WINDOW = PIP_SOUND_MAIN + 1;
-
-    // PIP layouts
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({
-            PIP_LAYOUT_BOTTOM_RIGHT, PIP_LAYOUT_TOP_RIGHT, PIP_LAYOUT_TOP_LEFT,
-            PIP_LAYOUT_BOTTOM_LEFT, PIP_LAYOUT_SIDE_BY_SIDE })
-    public @interface PipLayout {}
-    public static final int PIP_LAYOUT_BOTTOM_RIGHT = 0;
-    public static final int PIP_LAYOUT_TOP_RIGHT = PIP_LAYOUT_BOTTOM_RIGHT + 1;
-    public static final int PIP_LAYOUT_TOP_LEFT = PIP_LAYOUT_TOP_RIGHT + 1;
-    public static final int PIP_LAYOUT_BOTTOM_LEFT = PIP_LAYOUT_TOP_LEFT + 1;
-    public static final int PIP_LAYOUT_SIDE_BY_SIDE = PIP_LAYOUT_BOTTOM_LEFT + 1;
-    public static final int PIP_LAYOUT_LAST = PIP_LAYOUT_SIDE_BY_SIDE;
-
-    // PIP sizes
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef({ PIP_SIZE_SMALL, PIP_SIZE_BIG })
-    public @interface PipSize {}
-    public static final int PIP_SIZE_SMALL = 0;
-    public static final int PIP_SIZE_BIG = PIP_SIZE_SMALL + 1;
-    public static final int PIP_SIZE_LAST = PIP_SIZE_BIG;
-
     // Multi-track audio settings
     private static final String PREF_MULTI_AUDIO_ID = "pref.multi_audio_id";
     private static final String PREF_MULTI_AUDIO_LANGUAGE = "pref.multi_audio_language";
     private static final String PREF_MULTI_AUDIO_CHANNEL_COUNT = "pref.multi_audio_channel_count";
 
+    // DVR Multi-audio and subtitle settings
+    private static final String PREF_DVR_MULTI_AUDIO_ID = "pref.dvr_multi_audio_id";
+    private static final String PREF_DVR_MULTI_AUDIO_LANGUAGE = "pref.dvr_multi_audio_language";
+    private static final String PREF_DVR_MULTI_AUDIO_CHANNEL_COUNT =
+            "pref.dvr_multi_audio_channel_count";
+    private static final String PREF_DVR_SUBTITLE_ID = "pref.dvr_subtitle_id";
+    private static final String PREF_DVR_SUBTITLE_LANGUAGE = "pref.dvr_subtitle_language";
+
     // Parental Control settings
     private static final String PREF_CONTENT_RATING_SYSTEMS = "pref.content_rating_systems";
     private static final String PREF_CONTENT_RATING_LEVEL = "pref.content_rating_level";
@@ -89,58 +65,7 @@
     public static final int CONTENT_RATING_LEVEL_LOW = 3;
     public static final int CONTENT_RATING_LEVEL_CUSTOM = 4;
 
-    // PIP settings
-    /**
-     * Returns the layout of the PIP window stored in the shared preferences.
-     *
-     * @return the saved layout of the PIP window. This value is one of
-     *         {@link #PIP_LAYOUT_TOP_LEFT}, {@link #PIP_LAYOUT_TOP_RIGHT},
-     *         {@link #PIP_LAYOUT_BOTTOM_LEFT}, {@link #PIP_LAYOUT_BOTTOM_RIGHT} and
-     *         {@link #PIP_LAYOUT_SIDE_BY_SIDE}. If the preference value does not exist,
-     *         {@link #PIP_LAYOUT_BOTTOM_RIGHT} is returned.
-     */
-    @SuppressWarnings("ResourceType")
-    @PipLayout
-    public static int getPipLayout(Context context) {
-        return PreferenceManager.getDefaultSharedPreferences(context).getInt(
-                PREF_PIP_LAYOUT, PIP_LAYOUT_BOTTOM_RIGHT);
-    }
-
-    /**
-     * Stores the layout of PIP window to the shared preferences.
-     *
-     * @param pipLayout This value should be one of {@link #PIP_LAYOUT_TOP_LEFT},
-     *            {@link #PIP_LAYOUT_TOP_RIGHT}, {@link #PIP_LAYOUT_BOTTOM_LEFT},
-     *            {@link #PIP_LAYOUT_BOTTOM_RIGHT} and {@link #PIP_LAYOUT_SIDE_BY_SIDE}.
-     */
-    public static void setPipLayout(Context context, @PipLayout int pipLayout) {
-        PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(
-                PREF_PIP_LAYOUT, pipLayout).apply();
-    }
-
-    /**
-     * Returns the size of the PIP view stored in the shared preferences.
-     *
-     * @return the saved size of the PIP view. This value is one of
-     *         {@link #PIP_SIZE_SMALL} and {@link #PIP_SIZE_BIG}. If the preference value does not
-     *         exist, {@link #PIP_SIZE_SMALL} is returned.
-     */
-    @SuppressWarnings("ResourceType")
-    @PipSize
-    public static int getPipSize(Context context) {
-        return PreferenceManager.getDefaultSharedPreferences(context).getInt(
-                PREF_PIP_SIZE, PIP_SIZE_SMALL);
-    }
-
-    /**
-     * Stores the size of PIP view to the shared preferences.
-     *
-     * @param pipSize This value should be one of {@link #PIP_SIZE_SMALL} and {@link #PIP_SIZE_BIG}.
-     */
-    public static void setPipSize(Context context, @PipSize int pipSize) {
-        PreferenceManager.getDefaultSharedPreferences(context).edit().putInt(
-                PREF_PIP_SIZE, pipSize).apply();
-    }
+    private TvSettings() {}
 
     // Multi-track audio settings
     public static String getMultiAudioId(Context context) {
@@ -173,15 +98,58 @@
                 PREF_MULTI_AUDIO_CHANNEL_COUNT, channelCount).apply();
     }
 
-    // Parental Control settings
-    public static void addContentRatingSystems(Context context, Set<String> ids) {
-        Set<String> contentRatingSystemSet = getContentRatingSystemSet(context);
-        if (contentRatingSystemSet.addAll(ids)) {
-            PreferenceManager.getDefaultSharedPreferences(context).edit()
-                    .putStringSet(PREF_CONTENT_RATING_SYSTEMS, contentRatingSystemSet).apply();
+    public static void setDvrPlaybackTrackSettings(Context context, int trackType,
+            TvTrackInfo info) {
+        if (trackType == TvTrackInfo.TYPE_AUDIO) {
+            if (info == null) {
+                PreferenceManager.getDefaultSharedPreferences(context).edit()
+                        .remove(PREF_DVR_MULTI_AUDIO_ID).apply();
+            } else {
+                PreferenceManager.getDefaultSharedPreferences(context).edit()
+                        .putString(PREF_DVR_MULTI_AUDIO_LANGUAGE, info.getLanguage())
+                        .putInt(PREF_DVR_MULTI_AUDIO_CHANNEL_COUNT, info.getAudioChannelCount())
+                        .putString(PREF_DVR_MULTI_AUDIO_ID, info.getId()).apply();
+            }
+        } else if (trackType == TvTrackInfo.TYPE_SUBTITLE) {
+            if (info == null) {
+                PreferenceManager.getDefaultSharedPreferences(context).edit()
+                        .remove(PREF_DVR_SUBTITLE_ID).apply();
+            } else {
+                PreferenceManager.getDefaultSharedPreferences(context).edit()
+                        .putString(PREF_DVR_SUBTITLE_LANGUAGE, info.getLanguage())
+                        .putString(PREF_DVR_SUBTITLE_ID, info.getId()).apply();
+            }
         }
     }
 
+    public static TvTrackInfo getDvrPlaybackTrackSettings(Context context,
+            int trackType) {
+        String language;
+        String trackId;
+        int channelCount;
+        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context);
+        if (trackType == TvTrackInfo.TYPE_AUDIO) {
+            trackId = pref.getString(PREF_DVR_MULTI_AUDIO_ID, null);
+            if (trackId == null) {
+                return null;
+            }
+            language = pref.getString(PREF_DVR_MULTI_AUDIO_LANGUAGE, null);
+            channelCount = pref.getInt(PREF_DVR_MULTI_AUDIO_CHANNEL_COUNT, 0);
+            return new TvTrackInfo.Builder(trackType, trackId)
+                    .setLanguage(language).setAudioChannelCount(channelCount).build();
+        } else if (trackType == TvTrackInfo.TYPE_SUBTITLE) {
+            trackId = pref.getString(PREF_DVR_SUBTITLE_ID, null);
+            if (trackId == null) {
+                return null;
+            }
+            language = pref.getString(PREF_DVR_SUBTITLE_LANGUAGE, null);
+            return new TvTrackInfo.Builder(trackType, trackId).setLanguage(language).build();
+        } else {
+            return null;
+        }
+    }
+
+    // Parental Control settings
     public static void addContentRatingSystem(Context context, String id) {
         Set<String> contentRatingSystemSet = getContentRatingSystemSet(context);
         if (contentRatingSystemSet.add(id)) {
@@ -190,14 +158,6 @@
         }
     }
 
-    public static void removeContentRatingSystems(Context context, Set<String> ids) {
-        Set<String> contentRatingSystemSet = getContentRatingSystemSet(context);
-        if (contentRatingSystemSet.removeAll(ids)) {
-            PreferenceManager.getDefaultSharedPreferences(context).edit()
-                    .putStringSet(PREF_CONTENT_RATING_SYSTEMS, contentRatingSystemSet).apply();
-        }
-    }
-
     public static void removeContentRatingSystem(Context context, String id) {
         Set<String> contentRatingSystemSet = getContentRatingSystemSet(context);
         if (contentRatingSystemSet.remove(id)) {
@@ -254,4 +214,4 @@
         PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(
                 PREF_DISABLE_PIN_UNTIL, timeMillis).apply();
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/util/TvTrackInfoUtils.java b/src/com/android/tv/util/TvTrackInfoUtils.java
index c004f00..667cc9b 100644
--- a/src/com/android/tv/util/TvTrackInfoUtils.java
+++ b/src/com/android/tv/util/TvTrackInfoUtils.java
@@ -52,35 +52,22 @@
                 }
                 // Assumes {@code null} language matches to any language since it means user hasn't
                 // selected any track before or selected a track without language information.
-                boolean rhsLangMatch = language == null || Utils.isEqualLanguage(rhs.getLanguage(),
-                        language);
                 boolean lhsLangMatch = language == null || Utils.isEqualLanguage(lhs.getLanguage(),
                         language);
-                if (rhsLangMatch) {
-                    if (lhsLangMatch) {
-                        boolean rhsCountMatch = rhs.getAudioChannelCount() == channelCount;
-                        boolean lhsCountMatch = lhs.getAudioChannelCount() == channelCount;
-                        if (rhsCountMatch) {
-                            if (lhsCountMatch) {
-                                boolean rhsIdMatch = rhs.getId().equals(id);
-                                boolean lhsIdMatch = lhs.getId().equals(id);
-                                if (rhsIdMatch) {
-                                    return lhsIdMatch ? 0 : -1;
-                                } else {
-                                    return lhsIdMatch ? 1 : 0;
-                                }
-
-                            } else {
-                                return -1;
-                            }
-                        } else {
-                            return lhsCountMatch ? 1 : 0;
-                        }
+                boolean rhsLangMatch = language == null || Utils.isEqualLanguage(rhs.getLanguage(),
+                        language);
+                if (lhsLangMatch && rhsLangMatch) {
+                    boolean lhsCountMatch = lhs.getType() != TvTrackInfo.TYPE_AUDIO
+                            || lhs.getAudioChannelCount() == channelCount;
+                    boolean rhsCountMatch = rhs.getType() != TvTrackInfo.TYPE_AUDIO
+                            || rhs.getAudioChannelCount() == channelCount;
+                    if (lhsCountMatch && rhsCountMatch) {
+                        return Boolean.compare(lhs.getId().equals(id), rhs.getId().equals(id));
                     } else {
-                        return -1;
+                        return Boolean.compare(lhsCountMatch, rhsCountMatch);
                     }
                 } else {
-                    return lhsLangMatch ? 1 : 0;
+                    return Boolean.compare(lhsLangMatch, rhsLangMatch);
                 }
             }
         };
@@ -112,4 +99,4 @@
 
     private TvTrackInfoUtils() {
     }
-}
+}
\ No newline at end of file
diff --git a/src/com/android/tv/util/TvProviderUriMatcher.java b/src/com/android/tv/util/TvUriMatcher.java
similarity index 85%
rename from src/com/android/tv/util/TvProviderUriMatcher.java
rename to src/com/android/tv/util/TvUriMatcher.java
index 749e4aa..3d91cda 100644
--- a/src/com/android/tv/util/TvProviderUriMatcher.java
+++ b/src/com/android/tv/util/TvUriMatcher.java
@@ -16,23 +16,27 @@
 
 package com.android.tv.util;
 
+import android.app.SearchManager;
 import android.content.UriMatcher;
 import android.media.tv.TvContract;
 import android.net.Uri;
 import android.support.annotation.IntDef;
 
+import com.android.tv.search.LocalSearchProvider;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /**
  * Utility class to aid in matching URIs in TvProvider.
  */
-public class TvProviderUriMatcher {
+public class TvUriMatcher {
     private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({MATCH_CHANNEL, MATCH_CHANNEL_ID, MATCH_PROGRAM, MATCH_PROGRAM_ID,
-            MATCH_RECORDED_PROGRAM, MATCH_RECORDED_PROGRAM_ID, MATCH_WATCHED_PROGRAM_ID})
+            MATCH_RECORDED_PROGRAM, MATCH_RECORDED_PROGRAM_ID, MATCH_WATCHED_PROGRAM_ID,
+            MATCH_ON_DEVICE_SEARCH})
     private @interface TvProviderUriMatchCode {}
     /** The code for the channels URI. */
     public static final int MATCH_CHANNEL = 1;
@@ -48,6 +52,8 @@
     public static final int MATCH_RECORDED_PROGRAM_ID = 6;
     /** The code for the watched program URI. */
     public static final int MATCH_WATCHED_PROGRAM_ID = 7;
+    /** The code for the on-device search URI. */
+    public static final int MATCH_ON_DEVICE_SEARCH = 8;
     static {
         URI_MATCHER.addURI(TvContract.AUTHORITY, "channel", MATCH_CHANNEL);
         URI_MATCHER.addURI(TvContract.AUTHORITY, "channel/#", MATCH_CHANNEL_ID);
@@ -56,9 +62,11 @@
         URI_MATCHER.addURI(TvContract.AUTHORITY, "recorded_program", MATCH_RECORDED_PROGRAM);
         URI_MATCHER.addURI(TvContract.AUTHORITY, "recorded_program/#", MATCH_RECORDED_PROGRAM_ID);
         URI_MATCHER.addURI(TvContract.AUTHORITY, "watched_program/#", MATCH_WATCHED_PROGRAM_ID);
+        URI_MATCHER.addURI(LocalSearchProvider.AUTHORITY,
+                SearchManager.SUGGEST_URI_PATH_QUERY + "/*", MATCH_ON_DEVICE_SEARCH);
     }
 
-    private TvProviderUriMatcher() { }
+    private TvUriMatcher() { }
 
     /**
      * Try to match against the path in a url.
diff --git a/src/com/android/tv/util/Utils.java b/src/com/android/tv/util/Utils.java
index 99d3443..d11bab3 100644
--- a/src/com/android/tv/util/Utils.java
+++ b/src/com/android/tv/util/Utils.java
@@ -31,6 +31,7 @@
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvTrackInfo;
 import android.net.Uri;
+import android.os.Looper;
 import android.preference.PreferenceManager;
 import android.support.annotation.Nullable;
 import android.support.annotation.VisibleForTesting;
@@ -44,11 +45,13 @@
 import com.android.tv.ApplicationSingletons;
 import com.android.tv.R;
 import com.android.tv.TvApplication;
+import com.android.tv.common.BuildConfig;
 import com.android.tv.common.SoftPreconditions;
 import com.android.tv.data.Channel;
 import com.android.tv.data.GenreItems;
 import com.android.tv.data.Program;
 import com.android.tv.data.StreamInfo;
+import com.android.tv.experiments.Experiments;
 
 import java.io.File;
 import java.text.SimpleDateFormat;
@@ -62,6 +65,8 @@
 import java.util.Locale;
 import java.util.Set;
 import java.util.TimeZone;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -74,7 +79,6 @@
     private static final SimpleDateFormat ISO_8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",
             Locale.US);
 
-    public static final String EXTRA_KEY_KEYCODE = "keycode";
     public static final String EXTRA_KEY_ACTION = "action";
     public static final String EXTRA_ACTION_SHOW_TV_INPUT ="show_tv_input";
     public static final String EXTRA_KEY_FROM_LAUNCHER = "from_launcher";
@@ -83,11 +87,9 @@
     public static final String EXTRA_KEY_RECORDED_PROGRAM_PIN_CHECKED =
             "recorded_program_pin_checked";
 
-    // Query parameter in the intent of starting MainActivity.
-    public static final String PARAM_SOURCE = "source";
-
     private static final String PATH_CHANNEL = "channel";
     private static final String PATH_PROGRAM = "program";
+    private static final String PATH_RECORDED_PROGRAM = "recorded_program";
 
     private static final String PREF_KEY_LAST_WATCHED_CHANNEL_ID = "last_watched_channel_id";
     private static final String PREF_KEY_LAST_WATCHED_CHANNEL_ID_FOR_INPUT =
@@ -97,6 +99,8 @@
             "last_watched_tuner_input_id";
     private static final String PREF_KEY_RECORDING_FAILED_REASONS =
             "recording_failed_reasons";
+    private static final String PREF_KEY_FAILED_SCHEDULED_RECORDING_INFO_SET =
+            "failed_scheduled_recording_info_set";
 
     private static final int VIDEO_SD_WIDTH = 704;
     private static final int VIDEO_SD_HEIGHT = 480;
@@ -114,6 +118,7 @@
     private static final int AUDIO_CHANNEL_SURROUND_8 = 8;
 
     private static final long RECORDING_FAILED_REASON_NONE = 0;
+    private static final long HALF_MINUTE_MS = TimeUnit.SECONDS.toMillis(30);
     private static final long ONE_DAY_MS = TimeUnit.DAYS.toMillis(1);
 
     // Hardcoded list for known bundled inputs not written by OEM/SOCs.
@@ -207,6 +212,28 @@
     }
 
     /**
+     * Adds the info of failed scheduled recording.
+     */
+    public static void addFailedScheduledRecordingInfo(Context context,
+            String scheduledRecordingInfo) {
+        Set<String> failedScheduledRecordingInfoSet = getFailedScheduledRecordingInfoSet(context);
+        failedScheduledRecordingInfoSet.add(scheduledRecordingInfo);
+        PreferenceManager.getDefaultSharedPreferences(context).edit()
+                .putStringSet(PREF_KEY_FAILED_SCHEDULED_RECORDING_INFO_SET,
+                        failedScheduledRecordingInfoSet)
+                .apply();
+    }
+
+    /**
+     * Clears the failed scheduled recording info set.
+     */
+    public static void clearFailedScheduledRecordingInfoSet(Context context) {
+        PreferenceManager.getDefaultSharedPreferences(context).edit()
+                .remove(PREF_KEY_FAILED_SCHEDULED_RECORDING_INFO_SET)
+                .apply();
+    }
+
+    /**
      * Clears recording failed reason.
      */
     public static void clearRecordingFailedReason(Context context, int reason) {
@@ -246,6 +273,14 @@
     }
 
     /**
+     * Returns the failed scheduled recordings info set.
+     */
+    public static Set<String> getFailedScheduledRecordingInfoSet(Context context) {
+        return PreferenceManager.getDefaultSharedPreferences(context)
+                .getStringSet(PREF_KEY_FAILED_SCHEDULED_RECORDING_INFO_SET, new HashSet<>());
+    }
+
+    /**
      * Checks do recording failed reason exist.
      */
     public static boolean hasRecordingFailedReason(Context context, int reason) {
@@ -296,6 +331,13 @@
     }
 
     /**
+     * Returns {@code true}, if {@code uri} is a programs URI.
+     */
+    public static boolean isRecordedProgramsUri(Uri uri) {
+        return isTvUri(uri) && PATH_RECORDED_PROGRAM.equals(uri.getPathSegments().get(0));
+    }
+
+    /**
      * Gets the info of the program on particular time.
      */
     @WorkerThread
@@ -333,6 +375,14 @@
     }
 
     /**
+     * Returns the round off minutes when convert milliseconds to minutes.
+     */
+    public static int getRoundOffMinsFromMs(long millis) {
+        // Round off the result by adding half minute to the original ms.
+        return (int) TimeUnit.MILLISECONDS.toMinutes(millis + HALF_MINUTE_MS);
+    }
+
+    /**
      * Returns duration string according to the date & time format.
      * If {@code startUtcMillis} and {@code endUtcMills} are equal,
      * formatted time will be returned instead.
@@ -392,16 +442,18 @@
                 : DateUtils.formatDateRange(context, startUtcMillis, endUtcMillis + 1, flag);
     }
 
-    @VisibleForTesting
+    /**
+     * Checks if two given time (in milliseconds) are in the same day with regard to the
+     * locale timezone.
+     */
     public static boolean isInGivenDay(long dayToMatchInMillis, long subjectTimeInMillis) {
-        final long DAY_IN_MS = TimeUnit.DAYS.toMillis(1);
         TimeZone timeZone = Calendar.getInstance().getTimeZone();
         long offset = timeZone.getRawOffset();
         if (timeZone.inDaylightTime(new Date(dayToMatchInMillis))) {
             offset += timeZone.getDSTSavings();
         }
-        return Utils.floorTime(dayToMatchInMillis + offset, DAY_IN_MS)
-                == Utils.floorTime(subjectTimeInMillis + offset, DAY_IN_MS);
+        return Utils.floorTime(dayToMatchInMillis + offset, ONE_DAY_MS)
+                == Utils.floorTime(subjectTimeInMillis + offset, ONE_DAY_MS);
     }
 
     /**
@@ -523,7 +575,7 @@
         if (track.getType() != TvTrackInfo.TYPE_AUDIO) {
             throw new IllegalArgumentException("Not an audio track: " + track);
         }
-        String language = context.getString(R.string.default_language);
+        String language = context.getString(R.string.multi_audio_unknown_language);
         if (!TextUtils.isEmpty(track.getLanguage())) {
             language = new Locale(track.getLanguage()).getDisplayName();
         } else {
@@ -606,10 +658,12 @@
         if (input == null) {
             return null;
         }
-        CharSequence customLabel = input.loadCustomLabel(context);
+        TvInputManagerHelper inputManager =
+                TvApplication.getSingletons(context).getTvInputManagerHelper();
+        CharSequence customLabel = inputManager.loadCustomLabel(input);
         String label = (customLabel == null) ? null : customLabel.toString();
         if (TextUtils.isEmpty(label)) {
-            label = input.loadLabel(context).toString();
+            label = inputManager.loadLabel(input).toString();
         }
         return label;
     }
@@ -860,4 +914,28 @@
         }
         return Genres.encode(genres);
     }
+
+    /**
+     * Returns true if the current user is a developer.
+     */
+    public static boolean isDeveloper() {
+        return BuildConfig.ENG || Experiments.ENABLE_DEVELOPER_FEATURES.get();
+    }
+
+    /**
+     * Runs the method in main thread. If the current thread is not main thread, block it util
+     * the method is finished.
+     */
+    public static void runInMainThreadAndWait(Runnable runnable) {
+        if (Looper.myLooper() == Looper.getMainLooper()) {
+            runnable.run();
+        } else {
+            Future<?> temp = MainThreadExecutor.getInstance().submit(runnable);
+            try {
+                temp.get();
+            } catch (InterruptedException | ExecutionException e) {
+                Log.e(TAG, "failed to finish the execution", e);
+            }
+        }
+    }
 }
diff --git a/src/com/android/tv/util/ViewCache.java b/src/com/android/tv/util/ViewCache.java
new file mode 100644
index 0000000..ed9a8ff
--- /dev/null
+++ b/src/com/android/tv/util/ViewCache.java
@@ -0,0 +1,100 @@
+package com.android.tv.util;
+
+import android.content.Context;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+
+/**
+ * A cache for the views.
+ */
+public class ViewCache {
+    private final static SparseArray<ArrayList<View>> mViews = new SparseArray();
+
+    private static ViewCache sViewCache;
+
+    private ViewCache() { }
+
+    /**
+     * Returns an instance of the view cache.
+     */
+    public static ViewCache getInstance() {
+        if (sViewCache == null) {
+            sViewCache = new ViewCache();
+        }
+        return sViewCache;
+    }
+
+    /**
+     * Returns if the view cache is empty.
+     */
+    public boolean isEmpty() {
+        return mViews.size() == 0;
+    }
+
+    /**
+     * Stores a view into this view cache.
+     */
+    public void putView(int resId, View view) {
+        ArrayList<View> views = mViews.get(resId);
+        if (views == null) {
+            views = new ArrayList();
+            mViews.put(resId, views);
+        }
+        views.add(view);
+    }
+
+    /**
+     * Stores multi specific views into the view cache.
+     */
+    public void putView(Context context, int resId, ViewGroup fakeParent, int num) {
+        LayoutInflater inflater =
+                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        ArrayList<View> views = mViews.get(resId);
+        if (views == null) {
+            views = new ArrayList<>();
+            mViews.put(resId, views);
+        }
+        for (int i = 0; i < num; i++) {
+            View view = inflater.inflate(resId, fakeParent, false);
+            views.add(view);
+        }
+    }
+
+    /**
+     * Returns the view for specific resource id.
+     */
+    public View getView(int resId) {
+        ArrayList<View> views = mViews.get(resId);
+        if (views != null && !views.isEmpty()) {
+            View view = views.remove(views.size() - 1);
+            if (views.isEmpty()) {
+                mViews.remove(resId);
+            }
+            return view;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns the view if exists, or create a new view for the specific resource id.
+     */
+    public View getOrCreateView(LayoutInflater inflater, int resId, ViewGroup container) {
+        View view = getView(resId);
+        if (view == null) {
+            view = inflater.inflate(resId, container, false);
+        }
+        return view;
+    }
+
+    /**
+     * Clears the view cache.
+     */
+    public void clear() {
+        mViews.clear();
+    }
+}
diff --git a/tests/OWNERS b/tests/OWNERS
new file mode 100644
index 0000000..4aa5fe5
--- /dev/null
+++ b/tests/OWNERS
@@ -0,0 +1,2 @@
+nchalko@google.com
+shubang@google.com
diff --git a/tests/common/Android.mk b/tests/common/Android.mk
index aecd15b..27c9f03 100644
--- a/tests/common/Android.mk
+++ b/tests/common/Android.mk
@@ -17,7 +17,7 @@
 LOCAL_INSTRUMENTATION_FOR := LiveTv
 LOCAL_MODULE := tv-test-common
 LOCAL_MODULE_TAGS := optional
-LOCAL_SDK_VERSION := system_current
+LOCAL_SDK_VERSION := current
 
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 LOCAL_AIDL_INCLUDES += $(LOCAL_PATH)/src
diff --git a/tests/common/OWNERS b/tests/common/OWNERS
new file mode 100644
index 0000000..4aa5fe5
--- /dev/null
+++ b/tests/common/OWNERS
@@ -0,0 +1,2 @@
+nchalko@google.com
+shubang@google.com
diff --git a/tests/input/res/drawable-xhdpi/ch_1000_logo.png b/tests/common/res/drawable-xhdpi/ch_1000_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_1000_logo.png
rename to tests/common/res/drawable-xhdpi/ch_1000_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_100_logo.png b/tests/common/res/drawable-xhdpi/ch_100_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_100_logo.png
rename to tests/common/res/drawable-xhdpi/ch_100_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_101_logo.png b/tests/common/res/drawable-xhdpi/ch_101_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_101_logo.png
rename to tests/common/res/drawable-xhdpi/ch_101_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_102_logo.png b/tests/common/res/drawable-xhdpi/ch_102_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_102_logo.png
rename to tests/common/res/drawable-xhdpi/ch_102_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_103_logo.png b/tests/common/res/drawable-xhdpi/ch_103_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_103_logo.png
rename to tests/common/res/drawable-xhdpi/ch_103_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_104_logo.png b/tests/common/res/drawable-xhdpi/ch_104_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_104_logo.png
rename to tests/common/res/drawable-xhdpi/ch_104_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_105_logo.png b/tests/common/res/drawable-xhdpi/ch_105_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_105_logo.png
rename to tests/common/res/drawable-xhdpi/ch_105_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_106_logo.png b/tests/common/res/drawable-xhdpi/ch_106_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_106_logo.png
rename to tests/common/res/drawable-xhdpi/ch_106_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_107_logo.png b/tests/common/res/drawable-xhdpi/ch_107_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_107_logo.png
rename to tests/common/res/drawable-xhdpi/ch_107_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_108_logo.png b/tests/common/res/drawable-xhdpi/ch_108_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_108_logo.png
rename to tests/common/res/drawable-xhdpi/ch_108_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_109_logo.png b/tests/common/res/drawable-xhdpi/ch_109_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_109_logo.png
rename to tests/common/res/drawable-xhdpi/ch_109_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_10_logo.png b/tests/common/res/drawable-xhdpi/ch_10_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_10_logo.png
rename to tests/common/res/drawable-xhdpi/ch_10_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_110_logo.png b/tests/common/res/drawable-xhdpi/ch_110_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_110_logo.png
rename to tests/common/res/drawable-xhdpi/ch_110_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_111_logo.png b/tests/common/res/drawable-xhdpi/ch_111_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_111_logo.png
rename to tests/common/res/drawable-xhdpi/ch_111_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_112_logo.png b/tests/common/res/drawable-xhdpi/ch_112_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_112_logo.png
rename to tests/common/res/drawable-xhdpi/ch_112_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_113_logo.png b/tests/common/res/drawable-xhdpi/ch_113_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_113_logo.png
rename to tests/common/res/drawable-xhdpi/ch_113_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_114_logo.png b/tests/common/res/drawable-xhdpi/ch_114_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_114_logo.png
rename to tests/common/res/drawable-xhdpi/ch_114_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_115_logo.png b/tests/common/res/drawable-xhdpi/ch_115_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_115_logo.png
rename to tests/common/res/drawable-xhdpi/ch_115_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_116_logo.png b/tests/common/res/drawable-xhdpi/ch_116_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_116_logo.png
rename to tests/common/res/drawable-xhdpi/ch_116_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_117_logo.png b/tests/common/res/drawable-xhdpi/ch_117_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_117_logo.png
rename to tests/common/res/drawable-xhdpi/ch_117_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_118_logo.png b/tests/common/res/drawable-xhdpi/ch_118_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_118_logo.png
rename to tests/common/res/drawable-xhdpi/ch_118_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_119_logo.png b/tests/common/res/drawable-xhdpi/ch_119_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_119_logo.png
rename to tests/common/res/drawable-xhdpi/ch_119_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_11_logo.png b/tests/common/res/drawable-xhdpi/ch_11_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_11_logo.png
rename to tests/common/res/drawable-xhdpi/ch_11_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_120_logo.png b/tests/common/res/drawable-xhdpi/ch_120_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_120_logo.png
rename to tests/common/res/drawable-xhdpi/ch_120_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_121_logo.png b/tests/common/res/drawable-xhdpi/ch_121_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_121_logo.png
rename to tests/common/res/drawable-xhdpi/ch_121_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_122_logo.png b/tests/common/res/drawable-xhdpi/ch_122_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_122_logo.png
rename to tests/common/res/drawable-xhdpi/ch_122_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_123_logo.png b/tests/common/res/drawable-xhdpi/ch_123_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_123_logo.png
rename to tests/common/res/drawable-xhdpi/ch_123_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_124_logo.png b/tests/common/res/drawable-xhdpi/ch_124_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_124_logo.png
rename to tests/common/res/drawable-xhdpi/ch_124_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_125_logo.png b/tests/common/res/drawable-xhdpi/ch_125_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_125_logo.png
rename to tests/common/res/drawable-xhdpi/ch_125_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_126_logo.png b/tests/common/res/drawable-xhdpi/ch_126_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_126_logo.png
rename to tests/common/res/drawable-xhdpi/ch_126_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_127_logo.png b/tests/common/res/drawable-xhdpi/ch_127_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_127_logo.png
rename to tests/common/res/drawable-xhdpi/ch_127_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_128_logo.png b/tests/common/res/drawable-xhdpi/ch_128_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_128_logo.png
rename to tests/common/res/drawable-xhdpi/ch_128_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_129_logo.png b/tests/common/res/drawable-xhdpi/ch_129_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_129_logo.png
rename to tests/common/res/drawable-xhdpi/ch_129_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_12_logo.png b/tests/common/res/drawable-xhdpi/ch_12_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_12_logo.png
rename to tests/common/res/drawable-xhdpi/ch_12_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_130_logo.png b/tests/common/res/drawable-xhdpi/ch_130_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_130_logo.png
rename to tests/common/res/drawable-xhdpi/ch_130_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_131_logo.png b/tests/common/res/drawable-xhdpi/ch_131_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_131_logo.png
rename to tests/common/res/drawable-xhdpi/ch_131_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_132_logo.png b/tests/common/res/drawable-xhdpi/ch_132_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_132_logo.png
rename to tests/common/res/drawable-xhdpi/ch_132_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_133_logo.png b/tests/common/res/drawable-xhdpi/ch_133_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_133_logo.png
rename to tests/common/res/drawable-xhdpi/ch_133_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_134_logo.png b/tests/common/res/drawable-xhdpi/ch_134_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_134_logo.png
rename to tests/common/res/drawable-xhdpi/ch_134_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_135_logo.png b/tests/common/res/drawable-xhdpi/ch_135_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_135_logo.png
rename to tests/common/res/drawable-xhdpi/ch_135_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_136_logo.png b/tests/common/res/drawable-xhdpi/ch_136_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_136_logo.png
rename to tests/common/res/drawable-xhdpi/ch_136_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_137_logo.png b/tests/common/res/drawable-xhdpi/ch_137_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_137_logo.png
rename to tests/common/res/drawable-xhdpi/ch_137_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_138_logo.png b/tests/common/res/drawable-xhdpi/ch_138_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_138_logo.png
rename to tests/common/res/drawable-xhdpi/ch_138_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_139_logo.png b/tests/common/res/drawable-xhdpi/ch_139_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_139_logo.png
rename to tests/common/res/drawable-xhdpi/ch_139_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_13_logo.png b/tests/common/res/drawable-xhdpi/ch_13_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_13_logo.png
rename to tests/common/res/drawable-xhdpi/ch_13_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_140_logo.png b/tests/common/res/drawable-xhdpi/ch_140_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_140_logo.png
rename to tests/common/res/drawable-xhdpi/ch_140_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_141_logo.png b/tests/common/res/drawable-xhdpi/ch_141_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_141_logo.png
rename to tests/common/res/drawable-xhdpi/ch_141_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_142_logo.png b/tests/common/res/drawable-xhdpi/ch_142_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_142_logo.png
rename to tests/common/res/drawable-xhdpi/ch_142_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_143_logo.png b/tests/common/res/drawable-xhdpi/ch_143_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_143_logo.png
rename to tests/common/res/drawable-xhdpi/ch_143_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_144_logo.png b/tests/common/res/drawable-xhdpi/ch_144_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_144_logo.png
rename to tests/common/res/drawable-xhdpi/ch_144_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_145_logo.png b/tests/common/res/drawable-xhdpi/ch_145_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_145_logo.png
rename to tests/common/res/drawable-xhdpi/ch_145_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_146_logo.png b/tests/common/res/drawable-xhdpi/ch_146_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_146_logo.png
rename to tests/common/res/drawable-xhdpi/ch_146_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_147_logo.png b/tests/common/res/drawable-xhdpi/ch_147_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_147_logo.png
rename to tests/common/res/drawable-xhdpi/ch_147_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_148_logo.png b/tests/common/res/drawable-xhdpi/ch_148_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_148_logo.png
rename to tests/common/res/drawable-xhdpi/ch_148_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_149_logo.png b/tests/common/res/drawable-xhdpi/ch_149_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_149_logo.png
rename to tests/common/res/drawable-xhdpi/ch_149_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_14_logo.png b/tests/common/res/drawable-xhdpi/ch_14_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_14_logo.png
rename to tests/common/res/drawable-xhdpi/ch_14_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_150_logo.png b/tests/common/res/drawable-xhdpi/ch_150_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_150_logo.png
rename to tests/common/res/drawable-xhdpi/ch_150_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_151_logo.png b/tests/common/res/drawable-xhdpi/ch_151_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_151_logo.png
rename to tests/common/res/drawable-xhdpi/ch_151_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_152_logo.png b/tests/common/res/drawable-xhdpi/ch_152_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_152_logo.png
rename to tests/common/res/drawable-xhdpi/ch_152_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_153_logo.png b/tests/common/res/drawable-xhdpi/ch_153_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_153_logo.png
rename to tests/common/res/drawable-xhdpi/ch_153_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_154_logo.png b/tests/common/res/drawable-xhdpi/ch_154_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_154_logo.png
rename to tests/common/res/drawable-xhdpi/ch_154_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_155_logo.png b/tests/common/res/drawable-xhdpi/ch_155_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_155_logo.png
rename to tests/common/res/drawable-xhdpi/ch_155_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_156_logo.png b/tests/common/res/drawable-xhdpi/ch_156_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_156_logo.png
rename to tests/common/res/drawable-xhdpi/ch_156_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_157_logo.png b/tests/common/res/drawable-xhdpi/ch_157_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_157_logo.png
rename to tests/common/res/drawable-xhdpi/ch_157_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_158_logo.png b/tests/common/res/drawable-xhdpi/ch_158_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_158_logo.png
rename to tests/common/res/drawable-xhdpi/ch_158_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_159_logo.png b/tests/common/res/drawable-xhdpi/ch_159_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_159_logo.png
rename to tests/common/res/drawable-xhdpi/ch_159_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_15_logo.png b/tests/common/res/drawable-xhdpi/ch_15_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_15_logo.png
rename to tests/common/res/drawable-xhdpi/ch_15_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_160_logo.png b/tests/common/res/drawable-xhdpi/ch_160_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_160_logo.png
rename to tests/common/res/drawable-xhdpi/ch_160_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_161_logo.png b/tests/common/res/drawable-xhdpi/ch_161_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_161_logo.png
rename to tests/common/res/drawable-xhdpi/ch_161_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_162_logo.png b/tests/common/res/drawable-xhdpi/ch_162_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_162_logo.png
rename to tests/common/res/drawable-xhdpi/ch_162_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_163_logo.png b/tests/common/res/drawable-xhdpi/ch_163_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_163_logo.png
rename to tests/common/res/drawable-xhdpi/ch_163_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_164_logo.png b/tests/common/res/drawable-xhdpi/ch_164_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_164_logo.png
rename to tests/common/res/drawable-xhdpi/ch_164_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_165_logo.png b/tests/common/res/drawable-xhdpi/ch_165_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_165_logo.png
rename to tests/common/res/drawable-xhdpi/ch_165_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_166_logo.png b/tests/common/res/drawable-xhdpi/ch_166_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_166_logo.png
rename to tests/common/res/drawable-xhdpi/ch_166_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_167_logo.png b/tests/common/res/drawable-xhdpi/ch_167_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_167_logo.png
rename to tests/common/res/drawable-xhdpi/ch_167_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_168_logo.png b/tests/common/res/drawable-xhdpi/ch_168_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_168_logo.png
rename to tests/common/res/drawable-xhdpi/ch_168_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_169_logo.png b/tests/common/res/drawable-xhdpi/ch_169_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_169_logo.png
rename to tests/common/res/drawable-xhdpi/ch_169_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_16_logo.png b/tests/common/res/drawable-xhdpi/ch_16_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_16_logo.png
rename to tests/common/res/drawable-xhdpi/ch_16_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_170_logo.png b/tests/common/res/drawable-xhdpi/ch_170_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_170_logo.png
rename to tests/common/res/drawable-xhdpi/ch_170_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_171_logo.png b/tests/common/res/drawable-xhdpi/ch_171_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_171_logo.png
rename to tests/common/res/drawable-xhdpi/ch_171_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_172_logo.png b/tests/common/res/drawable-xhdpi/ch_172_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_172_logo.png
rename to tests/common/res/drawable-xhdpi/ch_172_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_173_logo.png b/tests/common/res/drawable-xhdpi/ch_173_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_173_logo.png
rename to tests/common/res/drawable-xhdpi/ch_173_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_174_logo.png b/tests/common/res/drawable-xhdpi/ch_174_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_174_logo.png
rename to tests/common/res/drawable-xhdpi/ch_174_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_175_logo.png b/tests/common/res/drawable-xhdpi/ch_175_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_175_logo.png
rename to tests/common/res/drawable-xhdpi/ch_175_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_176_logo.png b/tests/common/res/drawable-xhdpi/ch_176_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_176_logo.png
rename to tests/common/res/drawable-xhdpi/ch_176_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_177_logo.png b/tests/common/res/drawable-xhdpi/ch_177_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_177_logo.png
rename to tests/common/res/drawable-xhdpi/ch_177_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_178_logo.png b/tests/common/res/drawable-xhdpi/ch_178_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_178_logo.png
rename to tests/common/res/drawable-xhdpi/ch_178_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_179_logo.png b/tests/common/res/drawable-xhdpi/ch_179_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_179_logo.png
rename to tests/common/res/drawable-xhdpi/ch_179_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_17_logo.png b/tests/common/res/drawable-xhdpi/ch_17_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_17_logo.png
rename to tests/common/res/drawable-xhdpi/ch_17_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_180_logo.png b/tests/common/res/drawable-xhdpi/ch_180_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_180_logo.png
rename to tests/common/res/drawable-xhdpi/ch_180_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_181_logo.png b/tests/common/res/drawable-xhdpi/ch_181_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_181_logo.png
rename to tests/common/res/drawable-xhdpi/ch_181_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_182_logo.png b/tests/common/res/drawable-xhdpi/ch_182_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_182_logo.png
rename to tests/common/res/drawable-xhdpi/ch_182_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_183_logo.png b/tests/common/res/drawable-xhdpi/ch_183_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_183_logo.png
rename to tests/common/res/drawable-xhdpi/ch_183_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_184_logo.png b/tests/common/res/drawable-xhdpi/ch_184_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_184_logo.png
rename to tests/common/res/drawable-xhdpi/ch_184_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_185_logo.png b/tests/common/res/drawable-xhdpi/ch_185_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_185_logo.png
rename to tests/common/res/drawable-xhdpi/ch_185_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_186_logo.png b/tests/common/res/drawable-xhdpi/ch_186_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_186_logo.png
rename to tests/common/res/drawable-xhdpi/ch_186_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_187_logo.png b/tests/common/res/drawable-xhdpi/ch_187_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_187_logo.png
rename to tests/common/res/drawable-xhdpi/ch_187_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_188_logo.png b/tests/common/res/drawable-xhdpi/ch_188_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_188_logo.png
rename to tests/common/res/drawable-xhdpi/ch_188_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_189_logo.png b/tests/common/res/drawable-xhdpi/ch_189_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_189_logo.png
rename to tests/common/res/drawable-xhdpi/ch_189_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_18_logo.png b/tests/common/res/drawable-xhdpi/ch_18_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_18_logo.png
rename to tests/common/res/drawable-xhdpi/ch_18_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_190_logo.png b/tests/common/res/drawable-xhdpi/ch_190_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_190_logo.png
rename to tests/common/res/drawable-xhdpi/ch_190_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_191_logo.png b/tests/common/res/drawable-xhdpi/ch_191_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_191_logo.png
rename to tests/common/res/drawable-xhdpi/ch_191_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_192_logo.png b/tests/common/res/drawable-xhdpi/ch_192_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_192_logo.png
rename to tests/common/res/drawable-xhdpi/ch_192_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_193_logo.png b/tests/common/res/drawable-xhdpi/ch_193_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_193_logo.png
rename to tests/common/res/drawable-xhdpi/ch_193_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_194_logo.png b/tests/common/res/drawable-xhdpi/ch_194_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_194_logo.png
rename to tests/common/res/drawable-xhdpi/ch_194_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_195_logo.png b/tests/common/res/drawable-xhdpi/ch_195_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_195_logo.png
rename to tests/common/res/drawable-xhdpi/ch_195_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_196_logo.png b/tests/common/res/drawable-xhdpi/ch_196_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_196_logo.png
rename to tests/common/res/drawable-xhdpi/ch_196_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_197_logo.png b/tests/common/res/drawable-xhdpi/ch_197_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_197_logo.png
rename to tests/common/res/drawable-xhdpi/ch_197_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_198_logo.png b/tests/common/res/drawable-xhdpi/ch_198_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_198_logo.png
rename to tests/common/res/drawable-xhdpi/ch_198_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_199_logo.png b/tests/common/res/drawable-xhdpi/ch_199_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_199_logo.png
rename to tests/common/res/drawable-xhdpi/ch_199_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_19_logo.png b/tests/common/res/drawable-xhdpi/ch_19_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_19_logo.png
rename to tests/common/res/drawable-xhdpi/ch_19_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_1_logo.png b/tests/common/res/drawable-xhdpi/ch_1_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_1_logo.png
rename to tests/common/res/drawable-xhdpi/ch_1_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_200_logo.png b/tests/common/res/drawable-xhdpi/ch_200_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_200_logo.png
rename to tests/common/res/drawable-xhdpi/ch_200_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_201_logo.png b/tests/common/res/drawable-xhdpi/ch_201_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_201_logo.png
rename to tests/common/res/drawable-xhdpi/ch_201_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_202_logo.png b/tests/common/res/drawable-xhdpi/ch_202_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_202_logo.png
rename to tests/common/res/drawable-xhdpi/ch_202_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_203_logo.png b/tests/common/res/drawable-xhdpi/ch_203_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_203_logo.png
rename to tests/common/res/drawable-xhdpi/ch_203_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_204_logo.png b/tests/common/res/drawable-xhdpi/ch_204_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_204_logo.png
rename to tests/common/res/drawable-xhdpi/ch_204_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_205_logo.png b/tests/common/res/drawable-xhdpi/ch_205_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_205_logo.png
rename to tests/common/res/drawable-xhdpi/ch_205_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_206_logo.png b/tests/common/res/drawable-xhdpi/ch_206_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_206_logo.png
rename to tests/common/res/drawable-xhdpi/ch_206_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_207_logo.png b/tests/common/res/drawable-xhdpi/ch_207_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_207_logo.png
rename to tests/common/res/drawable-xhdpi/ch_207_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_208_logo.png b/tests/common/res/drawable-xhdpi/ch_208_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_208_logo.png
rename to tests/common/res/drawable-xhdpi/ch_208_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_209_logo.png b/tests/common/res/drawable-xhdpi/ch_209_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_209_logo.png
rename to tests/common/res/drawable-xhdpi/ch_209_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_20_logo.png b/tests/common/res/drawable-xhdpi/ch_20_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_20_logo.png
rename to tests/common/res/drawable-xhdpi/ch_20_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_210_logo.png b/tests/common/res/drawable-xhdpi/ch_210_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_210_logo.png
rename to tests/common/res/drawable-xhdpi/ch_210_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_211_logo.png b/tests/common/res/drawable-xhdpi/ch_211_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_211_logo.png
rename to tests/common/res/drawable-xhdpi/ch_211_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_212_logo.png b/tests/common/res/drawable-xhdpi/ch_212_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_212_logo.png
rename to tests/common/res/drawable-xhdpi/ch_212_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_213_logo.png b/tests/common/res/drawable-xhdpi/ch_213_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_213_logo.png
rename to tests/common/res/drawable-xhdpi/ch_213_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_214_logo.png b/tests/common/res/drawable-xhdpi/ch_214_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_214_logo.png
rename to tests/common/res/drawable-xhdpi/ch_214_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_215_logo.png b/tests/common/res/drawable-xhdpi/ch_215_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_215_logo.png
rename to tests/common/res/drawable-xhdpi/ch_215_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_216_logo.png b/tests/common/res/drawable-xhdpi/ch_216_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_216_logo.png
rename to tests/common/res/drawable-xhdpi/ch_216_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_217_logo.png b/tests/common/res/drawable-xhdpi/ch_217_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_217_logo.png
rename to tests/common/res/drawable-xhdpi/ch_217_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_218_logo.png b/tests/common/res/drawable-xhdpi/ch_218_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_218_logo.png
rename to tests/common/res/drawable-xhdpi/ch_218_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_219_logo.png b/tests/common/res/drawable-xhdpi/ch_219_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_219_logo.png
rename to tests/common/res/drawable-xhdpi/ch_219_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_21_logo.png b/tests/common/res/drawable-xhdpi/ch_21_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_21_logo.png
rename to tests/common/res/drawable-xhdpi/ch_21_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_220_logo.png b/tests/common/res/drawable-xhdpi/ch_220_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_220_logo.png
rename to tests/common/res/drawable-xhdpi/ch_220_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_221_logo.png b/tests/common/res/drawable-xhdpi/ch_221_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_221_logo.png
rename to tests/common/res/drawable-xhdpi/ch_221_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_222_logo.png b/tests/common/res/drawable-xhdpi/ch_222_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_222_logo.png
rename to tests/common/res/drawable-xhdpi/ch_222_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_223_logo.png b/tests/common/res/drawable-xhdpi/ch_223_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_223_logo.png
rename to tests/common/res/drawable-xhdpi/ch_223_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_224_logo.png b/tests/common/res/drawable-xhdpi/ch_224_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_224_logo.png
rename to tests/common/res/drawable-xhdpi/ch_224_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_225_logo.png b/tests/common/res/drawable-xhdpi/ch_225_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_225_logo.png
rename to tests/common/res/drawable-xhdpi/ch_225_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_226_logo.png b/tests/common/res/drawable-xhdpi/ch_226_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_226_logo.png
rename to tests/common/res/drawable-xhdpi/ch_226_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_227_logo.png b/tests/common/res/drawable-xhdpi/ch_227_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_227_logo.png
rename to tests/common/res/drawable-xhdpi/ch_227_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_228_logo.png b/tests/common/res/drawable-xhdpi/ch_228_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_228_logo.png
rename to tests/common/res/drawable-xhdpi/ch_228_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_229_logo.png b/tests/common/res/drawable-xhdpi/ch_229_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_229_logo.png
rename to tests/common/res/drawable-xhdpi/ch_229_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_22_logo.png b/tests/common/res/drawable-xhdpi/ch_22_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_22_logo.png
rename to tests/common/res/drawable-xhdpi/ch_22_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_230_logo.png b/tests/common/res/drawable-xhdpi/ch_230_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_230_logo.png
rename to tests/common/res/drawable-xhdpi/ch_230_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_231_logo.png b/tests/common/res/drawable-xhdpi/ch_231_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_231_logo.png
rename to tests/common/res/drawable-xhdpi/ch_231_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_232_logo.png b/tests/common/res/drawable-xhdpi/ch_232_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_232_logo.png
rename to tests/common/res/drawable-xhdpi/ch_232_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_233_logo.png b/tests/common/res/drawable-xhdpi/ch_233_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_233_logo.png
rename to tests/common/res/drawable-xhdpi/ch_233_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_234_logo.png b/tests/common/res/drawable-xhdpi/ch_234_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_234_logo.png
rename to tests/common/res/drawable-xhdpi/ch_234_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_235_logo.png b/tests/common/res/drawable-xhdpi/ch_235_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_235_logo.png
rename to tests/common/res/drawable-xhdpi/ch_235_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_236_logo.png b/tests/common/res/drawable-xhdpi/ch_236_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_236_logo.png
rename to tests/common/res/drawable-xhdpi/ch_236_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_237_logo.png b/tests/common/res/drawable-xhdpi/ch_237_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_237_logo.png
rename to tests/common/res/drawable-xhdpi/ch_237_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_238_logo.png b/tests/common/res/drawable-xhdpi/ch_238_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_238_logo.png
rename to tests/common/res/drawable-xhdpi/ch_238_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_239_logo.png b/tests/common/res/drawable-xhdpi/ch_239_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_239_logo.png
rename to tests/common/res/drawable-xhdpi/ch_239_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_23_logo.png b/tests/common/res/drawable-xhdpi/ch_23_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_23_logo.png
rename to tests/common/res/drawable-xhdpi/ch_23_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_240_logo.png b/tests/common/res/drawable-xhdpi/ch_240_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_240_logo.png
rename to tests/common/res/drawable-xhdpi/ch_240_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_241_logo.png b/tests/common/res/drawable-xhdpi/ch_241_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_241_logo.png
rename to tests/common/res/drawable-xhdpi/ch_241_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_242_logo.png b/tests/common/res/drawable-xhdpi/ch_242_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_242_logo.png
rename to tests/common/res/drawable-xhdpi/ch_242_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_243_logo.png b/tests/common/res/drawable-xhdpi/ch_243_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_243_logo.png
rename to tests/common/res/drawable-xhdpi/ch_243_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_244_logo.png b/tests/common/res/drawable-xhdpi/ch_244_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_244_logo.png
rename to tests/common/res/drawable-xhdpi/ch_244_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_245_logo.png b/tests/common/res/drawable-xhdpi/ch_245_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_245_logo.png
rename to tests/common/res/drawable-xhdpi/ch_245_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_246_logo.png b/tests/common/res/drawable-xhdpi/ch_246_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_246_logo.png
rename to tests/common/res/drawable-xhdpi/ch_246_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_247_logo.png b/tests/common/res/drawable-xhdpi/ch_247_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_247_logo.png
rename to tests/common/res/drawable-xhdpi/ch_247_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_248_logo.png b/tests/common/res/drawable-xhdpi/ch_248_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_248_logo.png
rename to tests/common/res/drawable-xhdpi/ch_248_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_249_logo.png b/tests/common/res/drawable-xhdpi/ch_249_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_249_logo.png
rename to tests/common/res/drawable-xhdpi/ch_249_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_24_logo.png b/tests/common/res/drawable-xhdpi/ch_24_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_24_logo.png
rename to tests/common/res/drawable-xhdpi/ch_24_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_250_logo.png b/tests/common/res/drawable-xhdpi/ch_250_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_250_logo.png
rename to tests/common/res/drawable-xhdpi/ch_250_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_251_logo.png b/tests/common/res/drawable-xhdpi/ch_251_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_251_logo.png
rename to tests/common/res/drawable-xhdpi/ch_251_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_252_logo.png b/tests/common/res/drawable-xhdpi/ch_252_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_252_logo.png
rename to tests/common/res/drawable-xhdpi/ch_252_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_253_logo.png b/tests/common/res/drawable-xhdpi/ch_253_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_253_logo.png
rename to tests/common/res/drawable-xhdpi/ch_253_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_254_logo.png b/tests/common/res/drawable-xhdpi/ch_254_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_254_logo.png
rename to tests/common/res/drawable-xhdpi/ch_254_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_255_logo.png b/tests/common/res/drawable-xhdpi/ch_255_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_255_logo.png
rename to tests/common/res/drawable-xhdpi/ch_255_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_256_logo.png b/tests/common/res/drawable-xhdpi/ch_256_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_256_logo.png
rename to tests/common/res/drawable-xhdpi/ch_256_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_257_logo.png b/tests/common/res/drawable-xhdpi/ch_257_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_257_logo.png
rename to tests/common/res/drawable-xhdpi/ch_257_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_258_logo.png b/tests/common/res/drawable-xhdpi/ch_258_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_258_logo.png
rename to tests/common/res/drawable-xhdpi/ch_258_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_259_logo.png b/tests/common/res/drawable-xhdpi/ch_259_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_259_logo.png
rename to tests/common/res/drawable-xhdpi/ch_259_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_25_logo.png b/tests/common/res/drawable-xhdpi/ch_25_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_25_logo.png
rename to tests/common/res/drawable-xhdpi/ch_25_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_260_logo.png b/tests/common/res/drawable-xhdpi/ch_260_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_260_logo.png
rename to tests/common/res/drawable-xhdpi/ch_260_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_261_logo.png b/tests/common/res/drawable-xhdpi/ch_261_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_261_logo.png
rename to tests/common/res/drawable-xhdpi/ch_261_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_262_logo.png b/tests/common/res/drawable-xhdpi/ch_262_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_262_logo.png
rename to tests/common/res/drawable-xhdpi/ch_262_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_263_logo.png b/tests/common/res/drawable-xhdpi/ch_263_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_263_logo.png
rename to tests/common/res/drawable-xhdpi/ch_263_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_264_logo.png b/tests/common/res/drawable-xhdpi/ch_264_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_264_logo.png
rename to tests/common/res/drawable-xhdpi/ch_264_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_265_logo.png b/tests/common/res/drawable-xhdpi/ch_265_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_265_logo.png
rename to tests/common/res/drawable-xhdpi/ch_265_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_266_logo.png b/tests/common/res/drawable-xhdpi/ch_266_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_266_logo.png
rename to tests/common/res/drawable-xhdpi/ch_266_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_267_logo.png b/tests/common/res/drawable-xhdpi/ch_267_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_267_logo.png
rename to tests/common/res/drawable-xhdpi/ch_267_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_268_logo.png b/tests/common/res/drawable-xhdpi/ch_268_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_268_logo.png
rename to tests/common/res/drawable-xhdpi/ch_268_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_269_logo.png b/tests/common/res/drawable-xhdpi/ch_269_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_269_logo.png
rename to tests/common/res/drawable-xhdpi/ch_269_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_26_logo.png b/tests/common/res/drawable-xhdpi/ch_26_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_26_logo.png
rename to tests/common/res/drawable-xhdpi/ch_26_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_270_logo.png b/tests/common/res/drawable-xhdpi/ch_270_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_270_logo.png
rename to tests/common/res/drawable-xhdpi/ch_270_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_271_logo.png b/tests/common/res/drawable-xhdpi/ch_271_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_271_logo.png
rename to tests/common/res/drawable-xhdpi/ch_271_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_272_logo.png b/tests/common/res/drawable-xhdpi/ch_272_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_272_logo.png
rename to tests/common/res/drawable-xhdpi/ch_272_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_273_logo.png b/tests/common/res/drawable-xhdpi/ch_273_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_273_logo.png
rename to tests/common/res/drawable-xhdpi/ch_273_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_274_logo.png b/tests/common/res/drawable-xhdpi/ch_274_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_274_logo.png
rename to tests/common/res/drawable-xhdpi/ch_274_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_275_logo.png b/tests/common/res/drawable-xhdpi/ch_275_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_275_logo.png
rename to tests/common/res/drawable-xhdpi/ch_275_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_276_logo.png b/tests/common/res/drawable-xhdpi/ch_276_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_276_logo.png
rename to tests/common/res/drawable-xhdpi/ch_276_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_277_logo.png b/tests/common/res/drawable-xhdpi/ch_277_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_277_logo.png
rename to tests/common/res/drawable-xhdpi/ch_277_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_278_logo.png b/tests/common/res/drawable-xhdpi/ch_278_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_278_logo.png
rename to tests/common/res/drawable-xhdpi/ch_278_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_279_logo.png b/tests/common/res/drawable-xhdpi/ch_279_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_279_logo.png
rename to tests/common/res/drawable-xhdpi/ch_279_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_27_logo.png b/tests/common/res/drawable-xhdpi/ch_27_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_27_logo.png
rename to tests/common/res/drawable-xhdpi/ch_27_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_280_logo.png b/tests/common/res/drawable-xhdpi/ch_280_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_280_logo.png
rename to tests/common/res/drawable-xhdpi/ch_280_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_281_logo.png b/tests/common/res/drawable-xhdpi/ch_281_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_281_logo.png
rename to tests/common/res/drawable-xhdpi/ch_281_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_282_logo.png b/tests/common/res/drawable-xhdpi/ch_282_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_282_logo.png
rename to tests/common/res/drawable-xhdpi/ch_282_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_283_logo.png b/tests/common/res/drawable-xhdpi/ch_283_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_283_logo.png
rename to tests/common/res/drawable-xhdpi/ch_283_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_284_logo.png b/tests/common/res/drawable-xhdpi/ch_284_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_284_logo.png
rename to tests/common/res/drawable-xhdpi/ch_284_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_285_logo.png b/tests/common/res/drawable-xhdpi/ch_285_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_285_logo.png
rename to tests/common/res/drawable-xhdpi/ch_285_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_286_logo.png b/tests/common/res/drawable-xhdpi/ch_286_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_286_logo.png
rename to tests/common/res/drawable-xhdpi/ch_286_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_287_logo.png b/tests/common/res/drawable-xhdpi/ch_287_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_287_logo.png
rename to tests/common/res/drawable-xhdpi/ch_287_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_288_logo.png b/tests/common/res/drawable-xhdpi/ch_288_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_288_logo.png
rename to tests/common/res/drawable-xhdpi/ch_288_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_289_logo.png b/tests/common/res/drawable-xhdpi/ch_289_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_289_logo.png
rename to tests/common/res/drawable-xhdpi/ch_289_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_28_logo.png b/tests/common/res/drawable-xhdpi/ch_28_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_28_logo.png
rename to tests/common/res/drawable-xhdpi/ch_28_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_290_logo.png b/tests/common/res/drawable-xhdpi/ch_290_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_290_logo.png
rename to tests/common/res/drawable-xhdpi/ch_290_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_291_logo.png b/tests/common/res/drawable-xhdpi/ch_291_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_291_logo.png
rename to tests/common/res/drawable-xhdpi/ch_291_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_292_logo.png b/tests/common/res/drawable-xhdpi/ch_292_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_292_logo.png
rename to tests/common/res/drawable-xhdpi/ch_292_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_293_logo.png b/tests/common/res/drawable-xhdpi/ch_293_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_293_logo.png
rename to tests/common/res/drawable-xhdpi/ch_293_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_294_logo.png b/tests/common/res/drawable-xhdpi/ch_294_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_294_logo.png
rename to tests/common/res/drawable-xhdpi/ch_294_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_295_logo.png b/tests/common/res/drawable-xhdpi/ch_295_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_295_logo.png
rename to tests/common/res/drawable-xhdpi/ch_295_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_296_logo.png b/tests/common/res/drawable-xhdpi/ch_296_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_296_logo.png
rename to tests/common/res/drawable-xhdpi/ch_296_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_297_logo.png b/tests/common/res/drawable-xhdpi/ch_297_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_297_logo.png
rename to tests/common/res/drawable-xhdpi/ch_297_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_298_logo.png b/tests/common/res/drawable-xhdpi/ch_298_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_298_logo.png
rename to tests/common/res/drawable-xhdpi/ch_298_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_299_logo.png b/tests/common/res/drawable-xhdpi/ch_299_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_299_logo.png
rename to tests/common/res/drawable-xhdpi/ch_299_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_29_logo.png b/tests/common/res/drawable-xhdpi/ch_29_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_29_logo.png
rename to tests/common/res/drawable-xhdpi/ch_29_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_2_logo.png b/tests/common/res/drawable-xhdpi/ch_2_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_2_logo.png
rename to tests/common/res/drawable-xhdpi/ch_2_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_300_logo.png b/tests/common/res/drawable-xhdpi/ch_300_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_300_logo.png
rename to tests/common/res/drawable-xhdpi/ch_300_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_301_logo.png b/tests/common/res/drawable-xhdpi/ch_301_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_301_logo.png
rename to tests/common/res/drawable-xhdpi/ch_301_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_302_logo.png b/tests/common/res/drawable-xhdpi/ch_302_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_302_logo.png
rename to tests/common/res/drawable-xhdpi/ch_302_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_303_logo.png b/tests/common/res/drawable-xhdpi/ch_303_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_303_logo.png
rename to tests/common/res/drawable-xhdpi/ch_303_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_304_logo.png b/tests/common/res/drawable-xhdpi/ch_304_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_304_logo.png
rename to tests/common/res/drawable-xhdpi/ch_304_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_305_logo.png b/tests/common/res/drawable-xhdpi/ch_305_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_305_logo.png
rename to tests/common/res/drawable-xhdpi/ch_305_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_306_logo.png b/tests/common/res/drawable-xhdpi/ch_306_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_306_logo.png
rename to tests/common/res/drawable-xhdpi/ch_306_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_307_logo.png b/tests/common/res/drawable-xhdpi/ch_307_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_307_logo.png
rename to tests/common/res/drawable-xhdpi/ch_307_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_308_logo.png b/tests/common/res/drawable-xhdpi/ch_308_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_308_logo.png
rename to tests/common/res/drawable-xhdpi/ch_308_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_309_logo.png b/tests/common/res/drawable-xhdpi/ch_309_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_309_logo.png
rename to tests/common/res/drawable-xhdpi/ch_309_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_30_logo.png b/tests/common/res/drawable-xhdpi/ch_30_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_30_logo.png
rename to tests/common/res/drawable-xhdpi/ch_30_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_310_logo.png b/tests/common/res/drawable-xhdpi/ch_310_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_310_logo.png
rename to tests/common/res/drawable-xhdpi/ch_310_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_311_logo.png b/tests/common/res/drawable-xhdpi/ch_311_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_311_logo.png
rename to tests/common/res/drawable-xhdpi/ch_311_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_312_logo.png b/tests/common/res/drawable-xhdpi/ch_312_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_312_logo.png
rename to tests/common/res/drawable-xhdpi/ch_312_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_313_logo.png b/tests/common/res/drawable-xhdpi/ch_313_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_313_logo.png
rename to tests/common/res/drawable-xhdpi/ch_313_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_314_logo.png b/tests/common/res/drawable-xhdpi/ch_314_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_314_logo.png
rename to tests/common/res/drawable-xhdpi/ch_314_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_315_logo.png b/tests/common/res/drawable-xhdpi/ch_315_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_315_logo.png
rename to tests/common/res/drawable-xhdpi/ch_315_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_316_logo.png b/tests/common/res/drawable-xhdpi/ch_316_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_316_logo.png
rename to tests/common/res/drawable-xhdpi/ch_316_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_317_logo.png b/tests/common/res/drawable-xhdpi/ch_317_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_317_logo.png
rename to tests/common/res/drawable-xhdpi/ch_317_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_318_logo.png b/tests/common/res/drawable-xhdpi/ch_318_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_318_logo.png
rename to tests/common/res/drawable-xhdpi/ch_318_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_319_logo.png b/tests/common/res/drawable-xhdpi/ch_319_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_319_logo.png
rename to tests/common/res/drawable-xhdpi/ch_319_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_31_logo.png b/tests/common/res/drawable-xhdpi/ch_31_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_31_logo.png
rename to tests/common/res/drawable-xhdpi/ch_31_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_320_logo.png b/tests/common/res/drawable-xhdpi/ch_320_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_320_logo.png
rename to tests/common/res/drawable-xhdpi/ch_320_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_321_logo.png b/tests/common/res/drawable-xhdpi/ch_321_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_321_logo.png
rename to tests/common/res/drawable-xhdpi/ch_321_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_322_logo.png b/tests/common/res/drawable-xhdpi/ch_322_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_322_logo.png
rename to tests/common/res/drawable-xhdpi/ch_322_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_323_logo.png b/tests/common/res/drawable-xhdpi/ch_323_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_323_logo.png
rename to tests/common/res/drawable-xhdpi/ch_323_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_324_logo.png b/tests/common/res/drawable-xhdpi/ch_324_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_324_logo.png
rename to tests/common/res/drawable-xhdpi/ch_324_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_325_logo.png b/tests/common/res/drawable-xhdpi/ch_325_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_325_logo.png
rename to tests/common/res/drawable-xhdpi/ch_325_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_326_logo.png b/tests/common/res/drawable-xhdpi/ch_326_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_326_logo.png
rename to tests/common/res/drawable-xhdpi/ch_326_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_327_logo.png b/tests/common/res/drawable-xhdpi/ch_327_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_327_logo.png
rename to tests/common/res/drawable-xhdpi/ch_327_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_328_logo.png b/tests/common/res/drawable-xhdpi/ch_328_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_328_logo.png
rename to tests/common/res/drawable-xhdpi/ch_328_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_329_logo.png b/tests/common/res/drawable-xhdpi/ch_329_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_329_logo.png
rename to tests/common/res/drawable-xhdpi/ch_329_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_32_logo.png b/tests/common/res/drawable-xhdpi/ch_32_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_32_logo.png
rename to tests/common/res/drawable-xhdpi/ch_32_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_330_logo.png b/tests/common/res/drawable-xhdpi/ch_330_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_330_logo.png
rename to tests/common/res/drawable-xhdpi/ch_330_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_331_logo.png b/tests/common/res/drawable-xhdpi/ch_331_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_331_logo.png
rename to tests/common/res/drawable-xhdpi/ch_331_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_332_logo.png b/tests/common/res/drawable-xhdpi/ch_332_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_332_logo.png
rename to tests/common/res/drawable-xhdpi/ch_332_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_333_logo.png b/tests/common/res/drawable-xhdpi/ch_333_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_333_logo.png
rename to tests/common/res/drawable-xhdpi/ch_333_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_334_logo.png b/tests/common/res/drawable-xhdpi/ch_334_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_334_logo.png
rename to tests/common/res/drawable-xhdpi/ch_334_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_335_logo.png b/tests/common/res/drawable-xhdpi/ch_335_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_335_logo.png
rename to tests/common/res/drawable-xhdpi/ch_335_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_336_logo.png b/tests/common/res/drawable-xhdpi/ch_336_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_336_logo.png
rename to tests/common/res/drawable-xhdpi/ch_336_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_337_logo.png b/tests/common/res/drawable-xhdpi/ch_337_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_337_logo.png
rename to tests/common/res/drawable-xhdpi/ch_337_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_338_logo.png b/tests/common/res/drawable-xhdpi/ch_338_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_338_logo.png
rename to tests/common/res/drawable-xhdpi/ch_338_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_339_logo.png b/tests/common/res/drawable-xhdpi/ch_339_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_339_logo.png
rename to tests/common/res/drawable-xhdpi/ch_339_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_33_logo.png b/tests/common/res/drawable-xhdpi/ch_33_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_33_logo.png
rename to tests/common/res/drawable-xhdpi/ch_33_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_340_logo.png b/tests/common/res/drawable-xhdpi/ch_340_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_340_logo.png
rename to tests/common/res/drawable-xhdpi/ch_340_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_341_logo.png b/tests/common/res/drawable-xhdpi/ch_341_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_341_logo.png
rename to tests/common/res/drawable-xhdpi/ch_341_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_342_logo.png b/tests/common/res/drawable-xhdpi/ch_342_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_342_logo.png
rename to tests/common/res/drawable-xhdpi/ch_342_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_343_logo.png b/tests/common/res/drawable-xhdpi/ch_343_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_343_logo.png
rename to tests/common/res/drawable-xhdpi/ch_343_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_344_logo.png b/tests/common/res/drawable-xhdpi/ch_344_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_344_logo.png
rename to tests/common/res/drawable-xhdpi/ch_344_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_345_logo.png b/tests/common/res/drawable-xhdpi/ch_345_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_345_logo.png
rename to tests/common/res/drawable-xhdpi/ch_345_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_346_logo.png b/tests/common/res/drawable-xhdpi/ch_346_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_346_logo.png
rename to tests/common/res/drawable-xhdpi/ch_346_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_347_logo.png b/tests/common/res/drawable-xhdpi/ch_347_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_347_logo.png
rename to tests/common/res/drawable-xhdpi/ch_347_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_348_logo.png b/tests/common/res/drawable-xhdpi/ch_348_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_348_logo.png
rename to tests/common/res/drawable-xhdpi/ch_348_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_349_logo.png b/tests/common/res/drawable-xhdpi/ch_349_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_349_logo.png
rename to tests/common/res/drawable-xhdpi/ch_349_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_34_logo.png b/tests/common/res/drawable-xhdpi/ch_34_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_34_logo.png
rename to tests/common/res/drawable-xhdpi/ch_34_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_350_logo.png b/tests/common/res/drawable-xhdpi/ch_350_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_350_logo.png
rename to tests/common/res/drawable-xhdpi/ch_350_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_351_logo.png b/tests/common/res/drawable-xhdpi/ch_351_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_351_logo.png
rename to tests/common/res/drawable-xhdpi/ch_351_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_352_logo.png b/tests/common/res/drawable-xhdpi/ch_352_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_352_logo.png
rename to tests/common/res/drawable-xhdpi/ch_352_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_353_logo.png b/tests/common/res/drawable-xhdpi/ch_353_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_353_logo.png
rename to tests/common/res/drawable-xhdpi/ch_353_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_354_logo.png b/tests/common/res/drawable-xhdpi/ch_354_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_354_logo.png
rename to tests/common/res/drawable-xhdpi/ch_354_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_355_logo.png b/tests/common/res/drawable-xhdpi/ch_355_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_355_logo.png
rename to tests/common/res/drawable-xhdpi/ch_355_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_356_logo.png b/tests/common/res/drawable-xhdpi/ch_356_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_356_logo.png
rename to tests/common/res/drawable-xhdpi/ch_356_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_357_logo.png b/tests/common/res/drawable-xhdpi/ch_357_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_357_logo.png
rename to tests/common/res/drawable-xhdpi/ch_357_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_358_logo.png b/tests/common/res/drawable-xhdpi/ch_358_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_358_logo.png
rename to tests/common/res/drawable-xhdpi/ch_358_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_359_logo.png b/tests/common/res/drawable-xhdpi/ch_359_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_359_logo.png
rename to tests/common/res/drawable-xhdpi/ch_359_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_35_logo.png b/tests/common/res/drawable-xhdpi/ch_35_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_35_logo.png
rename to tests/common/res/drawable-xhdpi/ch_35_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_360_logo.png b/tests/common/res/drawable-xhdpi/ch_360_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_360_logo.png
rename to tests/common/res/drawable-xhdpi/ch_360_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_361_logo.png b/tests/common/res/drawable-xhdpi/ch_361_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_361_logo.png
rename to tests/common/res/drawable-xhdpi/ch_361_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_362_logo.png b/tests/common/res/drawable-xhdpi/ch_362_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_362_logo.png
rename to tests/common/res/drawable-xhdpi/ch_362_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_363_logo.png b/tests/common/res/drawable-xhdpi/ch_363_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_363_logo.png
rename to tests/common/res/drawable-xhdpi/ch_363_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_364_logo.png b/tests/common/res/drawable-xhdpi/ch_364_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_364_logo.png
rename to tests/common/res/drawable-xhdpi/ch_364_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_365_logo.png b/tests/common/res/drawable-xhdpi/ch_365_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_365_logo.png
rename to tests/common/res/drawable-xhdpi/ch_365_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_366_logo.png b/tests/common/res/drawable-xhdpi/ch_366_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_366_logo.png
rename to tests/common/res/drawable-xhdpi/ch_366_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_367_logo.png b/tests/common/res/drawable-xhdpi/ch_367_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_367_logo.png
rename to tests/common/res/drawable-xhdpi/ch_367_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_368_logo.png b/tests/common/res/drawable-xhdpi/ch_368_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_368_logo.png
rename to tests/common/res/drawable-xhdpi/ch_368_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_369_logo.png b/tests/common/res/drawable-xhdpi/ch_369_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_369_logo.png
rename to tests/common/res/drawable-xhdpi/ch_369_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_36_logo.png b/tests/common/res/drawable-xhdpi/ch_36_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_36_logo.png
rename to tests/common/res/drawable-xhdpi/ch_36_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_370_logo.png b/tests/common/res/drawable-xhdpi/ch_370_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_370_logo.png
rename to tests/common/res/drawable-xhdpi/ch_370_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_371_logo.png b/tests/common/res/drawable-xhdpi/ch_371_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_371_logo.png
rename to tests/common/res/drawable-xhdpi/ch_371_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_372_logo.png b/tests/common/res/drawable-xhdpi/ch_372_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_372_logo.png
rename to tests/common/res/drawable-xhdpi/ch_372_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_373_logo.png b/tests/common/res/drawable-xhdpi/ch_373_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_373_logo.png
rename to tests/common/res/drawable-xhdpi/ch_373_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_374_logo.png b/tests/common/res/drawable-xhdpi/ch_374_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_374_logo.png
rename to tests/common/res/drawable-xhdpi/ch_374_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_375_logo.png b/tests/common/res/drawable-xhdpi/ch_375_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_375_logo.png
rename to tests/common/res/drawable-xhdpi/ch_375_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_376_logo.png b/tests/common/res/drawable-xhdpi/ch_376_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_376_logo.png
rename to tests/common/res/drawable-xhdpi/ch_376_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_377_logo.png b/tests/common/res/drawable-xhdpi/ch_377_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_377_logo.png
rename to tests/common/res/drawable-xhdpi/ch_377_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_378_logo.png b/tests/common/res/drawable-xhdpi/ch_378_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_378_logo.png
rename to tests/common/res/drawable-xhdpi/ch_378_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_379_logo.png b/tests/common/res/drawable-xhdpi/ch_379_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_379_logo.png
rename to tests/common/res/drawable-xhdpi/ch_379_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_37_logo.png b/tests/common/res/drawable-xhdpi/ch_37_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_37_logo.png
rename to tests/common/res/drawable-xhdpi/ch_37_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_380_logo.png b/tests/common/res/drawable-xhdpi/ch_380_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_380_logo.png
rename to tests/common/res/drawable-xhdpi/ch_380_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_381_logo.png b/tests/common/res/drawable-xhdpi/ch_381_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_381_logo.png
rename to tests/common/res/drawable-xhdpi/ch_381_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_382_logo.png b/tests/common/res/drawable-xhdpi/ch_382_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_382_logo.png
rename to tests/common/res/drawable-xhdpi/ch_382_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_383_logo.png b/tests/common/res/drawable-xhdpi/ch_383_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_383_logo.png
rename to tests/common/res/drawable-xhdpi/ch_383_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_384_logo.png b/tests/common/res/drawable-xhdpi/ch_384_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_384_logo.png
rename to tests/common/res/drawable-xhdpi/ch_384_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_385_logo.png b/tests/common/res/drawable-xhdpi/ch_385_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_385_logo.png
rename to tests/common/res/drawable-xhdpi/ch_385_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_386_logo.png b/tests/common/res/drawable-xhdpi/ch_386_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_386_logo.png
rename to tests/common/res/drawable-xhdpi/ch_386_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_387_logo.png b/tests/common/res/drawable-xhdpi/ch_387_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_387_logo.png
rename to tests/common/res/drawable-xhdpi/ch_387_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_388_logo.png b/tests/common/res/drawable-xhdpi/ch_388_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_388_logo.png
rename to tests/common/res/drawable-xhdpi/ch_388_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_389_logo.png b/tests/common/res/drawable-xhdpi/ch_389_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_389_logo.png
rename to tests/common/res/drawable-xhdpi/ch_389_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_38_logo.png b/tests/common/res/drawable-xhdpi/ch_38_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_38_logo.png
rename to tests/common/res/drawable-xhdpi/ch_38_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_390_logo.png b/tests/common/res/drawable-xhdpi/ch_390_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_390_logo.png
rename to tests/common/res/drawable-xhdpi/ch_390_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_391_logo.png b/tests/common/res/drawable-xhdpi/ch_391_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_391_logo.png
rename to tests/common/res/drawable-xhdpi/ch_391_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_392_logo.png b/tests/common/res/drawable-xhdpi/ch_392_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_392_logo.png
rename to tests/common/res/drawable-xhdpi/ch_392_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_393_logo.png b/tests/common/res/drawable-xhdpi/ch_393_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_393_logo.png
rename to tests/common/res/drawable-xhdpi/ch_393_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_394_logo.png b/tests/common/res/drawable-xhdpi/ch_394_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_394_logo.png
rename to tests/common/res/drawable-xhdpi/ch_394_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_395_logo.png b/tests/common/res/drawable-xhdpi/ch_395_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_395_logo.png
rename to tests/common/res/drawable-xhdpi/ch_395_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_396_logo.png b/tests/common/res/drawable-xhdpi/ch_396_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_396_logo.png
rename to tests/common/res/drawable-xhdpi/ch_396_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_397_logo.png b/tests/common/res/drawable-xhdpi/ch_397_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_397_logo.png
rename to tests/common/res/drawable-xhdpi/ch_397_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_398_logo.png b/tests/common/res/drawable-xhdpi/ch_398_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_398_logo.png
rename to tests/common/res/drawable-xhdpi/ch_398_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_399_logo.png b/tests/common/res/drawable-xhdpi/ch_399_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_399_logo.png
rename to tests/common/res/drawable-xhdpi/ch_399_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_39_logo.png b/tests/common/res/drawable-xhdpi/ch_39_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_39_logo.png
rename to tests/common/res/drawable-xhdpi/ch_39_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_3_logo.png b/tests/common/res/drawable-xhdpi/ch_3_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_3_logo.png
rename to tests/common/res/drawable-xhdpi/ch_3_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_400_logo.png b/tests/common/res/drawable-xhdpi/ch_400_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_400_logo.png
rename to tests/common/res/drawable-xhdpi/ch_400_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_401_logo.png b/tests/common/res/drawable-xhdpi/ch_401_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_401_logo.png
rename to tests/common/res/drawable-xhdpi/ch_401_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_402_logo.png b/tests/common/res/drawable-xhdpi/ch_402_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_402_logo.png
rename to tests/common/res/drawable-xhdpi/ch_402_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_403_logo.png b/tests/common/res/drawable-xhdpi/ch_403_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_403_logo.png
rename to tests/common/res/drawable-xhdpi/ch_403_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_404_logo.png b/tests/common/res/drawable-xhdpi/ch_404_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_404_logo.png
rename to tests/common/res/drawable-xhdpi/ch_404_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_405_logo.png b/tests/common/res/drawable-xhdpi/ch_405_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_405_logo.png
rename to tests/common/res/drawable-xhdpi/ch_405_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_406_logo.png b/tests/common/res/drawable-xhdpi/ch_406_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_406_logo.png
rename to tests/common/res/drawable-xhdpi/ch_406_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_407_logo.png b/tests/common/res/drawable-xhdpi/ch_407_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_407_logo.png
rename to tests/common/res/drawable-xhdpi/ch_407_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_408_logo.png b/tests/common/res/drawable-xhdpi/ch_408_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_408_logo.png
rename to tests/common/res/drawable-xhdpi/ch_408_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_409_logo.png b/tests/common/res/drawable-xhdpi/ch_409_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_409_logo.png
rename to tests/common/res/drawable-xhdpi/ch_409_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_40_logo.png b/tests/common/res/drawable-xhdpi/ch_40_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_40_logo.png
rename to tests/common/res/drawable-xhdpi/ch_40_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_410_logo.png b/tests/common/res/drawable-xhdpi/ch_410_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_410_logo.png
rename to tests/common/res/drawable-xhdpi/ch_410_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_411_logo.png b/tests/common/res/drawable-xhdpi/ch_411_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_411_logo.png
rename to tests/common/res/drawable-xhdpi/ch_411_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_412_logo.png b/tests/common/res/drawable-xhdpi/ch_412_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_412_logo.png
rename to tests/common/res/drawable-xhdpi/ch_412_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_413_logo.png b/tests/common/res/drawable-xhdpi/ch_413_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_413_logo.png
rename to tests/common/res/drawable-xhdpi/ch_413_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_414_logo.png b/tests/common/res/drawable-xhdpi/ch_414_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_414_logo.png
rename to tests/common/res/drawable-xhdpi/ch_414_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_415_logo.png b/tests/common/res/drawable-xhdpi/ch_415_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_415_logo.png
rename to tests/common/res/drawable-xhdpi/ch_415_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_416_logo.png b/tests/common/res/drawable-xhdpi/ch_416_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_416_logo.png
rename to tests/common/res/drawable-xhdpi/ch_416_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_417_logo.png b/tests/common/res/drawable-xhdpi/ch_417_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_417_logo.png
rename to tests/common/res/drawable-xhdpi/ch_417_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_418_logo.png b/tests/common/res/drawable-xhdpi/ch_418_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_418_logo.png
rename to tests/common/res/drawable-xhdpi/ch_418_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_419_logo.png b/tests/common/res/drawable-xhdpi/ch_419_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_419_logo.png
rename to tests/common/res/drawable-xhdpi/ch_419_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_41_logo.png b/tests/common/res/drawable-xhdpi/ch_41_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_41_logo.png
rename to tests/common/res/drawable-xhdpi/ch_41_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_420_logo.png b/tests/common/res/drawable-xhdpi/ch_420_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_420_logo.png
rename to tests/common/res/drawable-xhdpi/ch_420_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_421_logo.png b/tests/common/res/drawable-xhdpi/ch_421_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_421_logo.png
rename to tests/common/res/drawable-xhdpi/ch_421_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_422_logo.png b/tests/common/res/drawable-xhdpi/ch_422_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_422_logo.png
rename to tests/common/res/drawable-xhdpi/ch_422_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_423_logo.png b/tests/common/res/drawable-xhdpi/ch_423_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_423_logo.png
rename to tests/common/res/drawable-xhdpi/ch_423_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_424_logo.png b/tests/common/res/drawable-xhdpi/ch_424_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_424_logo.png
rename to tests/common/res/drawable-xhdpi/ch_424_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_425_logo.png b/tests/common/res/drawable-xhdpi/ch_425_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_425_logo.png
rename to tests/common/res/drawable-xhdpi/ch_425_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_426_logo.png b/tests/common/res/drawable-xhdpi/ch_426_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_426_logo.png
rename to tests/common/res/drawable-xhdpi/ch_426_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_427_logo.png b/tests/common/res/drawable-xhdpi/ch_427_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_427_logo.png
rename to tests/common/res/drawable-xhdpi/ch_427_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_428_logo.png b/tests/common/res/drawable-xhdpi/ch_428_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_428_logo.png
rename to tests/common/res/drawable-xhdpi/ch_428_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_429_logo.png b/tests/common/res/drawable-xhdpi/ch_429_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_429_logo.png
rename to tests/common/res/drawable-xhdpi/ch_429_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_42_logo.png b/tests/common/res/drawable-xhdpi/ch_42_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_42_logo.png
rename to tests/common/res/drawable-xhdpi/ch_42_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_430_logo.png b/tests/common/res/drawable-xhdpi/ch_430_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_430_logo.png
rename to tests/common/res/drawable-xhdpi/ch_430_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_431_logo.png b/tests/common/res/drawable-xhdpi/ch_431_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_431_logo.png
rename to tests/common/res/drawable-xhdpi/ch_431_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_432_logo.png b/tests/common/res/drawable-xhdpi/ch_432_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_432_logo.png
rename to tests/common/res/drawable-xhdpi/ch_432_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_433_logo.png b/tests/common/res/drawable-xhdpi/ch_433_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_433_logo.png
rename to tests/common/res/drawable-xhdpi/ch_433_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_434_logo.png b/tests/common/res/drawable-xhdpi/ch_434_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_434_logo.png
rename to tests/common/res/drawable-xhdpi/ch_434_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_435_logo.png b/tests/common/res/drawable-xhdpi/ch_435_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_435_logo.png
rename to tests/common/res/drawable-xhdpi/ch_435_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_436_logo.png b/tests/common/res/drawable-xhdpi/ch_436_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_436_logo.png
rename to tests/common/res/drawable-xhdpi/ch_436_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_437_logo.png b/tests/common/res/drawable-xhdpi/ch_437_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_437_logo.png
rename to tests/common/res/drawable-xhdpi/ch_437_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_438_logo.png b/tests/common/res/drawable-xhdpi/ch_438_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_438_logo.png
rename to tests/common/res/drawable-xhdpi/ch_438_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_439_logo.png b/tests/common/res/drawable-xhdpi/ch_439_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_439_logo.png
rename to tests/common/res/drawable-xhdpi/ch_439_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_43_logo.png b/tests/common/res/drawable-xhdpi/ch_43_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_43_logo.png
rename to tests/common/res/drawable-xhdpi/ch_43_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_440_logo.png b/tests/common/res/drawable-xhdpi/ch_440_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_440_logo.png
rename to tests/common/res/drawable-xhdpi/ch_440_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_441_logo.png b/tests/common/res/drawable-xhdpi/ch_441_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_441_logo.png
rename to tests/common/res/drawable-xhdpi/ch_441_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_442_logo.png b/tests/common/res/drawable-xhdpi/ch_442_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_442_logo.png
rename to tests/common/res/drawable-xhdpi/ch_442_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_443_logo.png b/tests/common/res/drawable-xhdpi/ch_443_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_443_logo.png
rename to tests/common/res/drawable-xhdpi/ch_443_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_444_logo.png b/tests/common/res/drawable-xhdpi/ch_444_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_444_logo.png
rename to tests/common/res/drawable-xhdpi/ch_444_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_445_logo.png b/tests/common/res/drawable-xhdpi/ch_445_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_445_logo.png
rename to tests/common/res/drawable-xhdpi/ch_445_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_446_logo.png b/tests/common/res/drawable-xhdpi/ch_446_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_446_logo.png
rename to tests/common/res/drawable-xhdpi/ch_446_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_447_logo.png b/tests/common/res/drawable-xhdpi/ch_447_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_447_logo.png
rename to tests/common/res/drawable-xhdpi/ch_447_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_448_logo.png b/tests/common/res/drawable-xhdpi/ch_448_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_448_logo.png
rename to tests/common/res/drawable-xhdpi/ch_448_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_449_logo.png b/tests/common/res/drawable-xhdpi/ch_449_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_449_logo.png
rename to tests/common/res/drawable-xhdpi/ch_449_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_44_logo.png b/tests/common/res/drawable-xhdpi/ch_44_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_44_logo.png
rename to tests/common/res/drawable-xhdpi/ch_44_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_450_logo.png b/tests/common/res/drawable-xhdpi/ch_450_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_450_logo.png
rename to tests/common/res/drawable-xhdpi/ch_450_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_451_logo.png b/tests/common/res/drawable-xhdpi/ch_451_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_451_logo.png
rename to tests/common/res/drawable-xhdpi/ch_451_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_452_logo.png b/tests/common/res/drawable-xhdpi/ch_452_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_452_logo.png
rename to tests/common/res/drawable-xhdpi/ch_452_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_453_logo.png b/tests/common/res/drawable-xhdpi/ch_453_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_453_logo.png
rename to tests/common/res/drawable-xhdpi/ch_453_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_454_logo.png b/tests/common/res/drawable-xhdpi/ch_454_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_454_logo.png
rename to tests/common/res/drawable-xhdpi/ch_454_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_455_logo.png b/tests/common/res/drawable-xhdpi/ch_455_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_455_logo.png
rename to tests/common/res/drawable-xhdpi/ch_455_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_456_logo.png b/tests/common/res/drawable-xhdpi/ch_456_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_456_logo.png
rename to tests/common/res/drawable-xhdpi/ch_456_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_457_logo.png b/tests/common/res/drawable-xhdpi/ch_457_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_457_logo.png
rename to tests/common/res/drawable-xhdpi/ch_457_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_458_logo.png b/tests/common/res/drawable-xhdpi/ch_458_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_458_logo.png
rename to tests/common/res/drawable-xhdpi/ch_458_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_459_logo.png b/tests/common/res/drawable-xhdpi/ch_459_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_459_logo.png
rename to tests/common/res/drawable-xhdpi/ch_459_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_45_logo.png b/tests/common/res/drawable-xhdpi/ch_45_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_45_logo.png
rename to tests/common/res/drawable-xhdpi/ch_45_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_460_logo.png b/tests/common/res/drawable-xhdpi/ch_460_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_460_logo.png
rename to tests/common/res/drawable-xhdpi/ch_460_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_461_logo.png b/tests/common/res/drawable-xhdpi/ch_461_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_461_logo.png
rename to tests/common/res/drawable-xhdpi/ch_461_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_462_logo.png b/tests/common/res/drawable-xhdpi/ch_462_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_462_logo.png
rename to tests/common/res/drawable-xhdpi/ch_462_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_463_logo.png b/tests/common/res/drawable-xhdpi/ch_463_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_463_logo.png
rename to tests/common/res/drawable-xhdpi/ch_463_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_464_logo.png b/tests/common/res/drawable-xhdpi/ch_464_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_464_logo.png
rename to tests/common/res/drawable-xhdpi/ch_464_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_465_logo.png b/tests/common/res/drawable-xhdpi/ch_465_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_465_logo.png
rename to tests/common/res/drawable-xhdpi/ch_465_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_466_logo.png b/tests/common/res/drawable-xhdpi/ch_466_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_466_logo.png
rename to tests/common/res/drawable-xhdpi/ch_466_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_467_logo.png b/tests/common/res/drawable-xhdpi/ch_467_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_467_logo.png
rename to tests/common/res/drawable-xhdpi/ch_467_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_468_logo.png b/tests/common/res/drawable-xhdpi/ch_468_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_468_logo.png
rename to tests/common/res/drawable-xhdpi/ch_468_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_469_logo.png b/tests/common/res/drawable-xhdpi/ch_469_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_469_logo.png
rename to tests/common/res/drawable-xhdpi/ch_469_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_46_logo.png b/tests/common/res/drawable-xhdpi/ch_46_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_46_logo.png
rename to tests/common/res/drawable-xhdpi/ch_46_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_470_logo.png b/tests/common/res/drawable-xhdpi/ch_470_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_470_logo.png
rename to tests/common/res/drawable-xhdpi/ch_470_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_471_logo.png b/tests/common/res/drawable-xhdpi/ch_471_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_471_logo.png
rename to tests/common/res/drawable-xhdpi/ch_471_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_472_logo.png b/tests/common/res/drawable-xhdpi/ch_472_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_472_logo.png
rename to tests/common/res/drawable-xhdpi/ch_472_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_473_logo.png b/tests/common/res/drawable-xhdpi/ch_473_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_473_logo.png
rename to tests/common/res/drawable-xhdpi/ch_473_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_474_logo.png b/tests/common/res/drawable-xhdpi/ch_474_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_474_logo.png
rename to tests/common/res/drawable-xhdpi/ch_474_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_475_logo.png b/tests/common/res/drawable-xhdpi/ch_475_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_475_logo.png
rename to tests/common/res/drawable-xhdpi/ch_475_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_476_logo.png b/tests/common/res/drawable-xhdpi/ch_476_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_476_logo.png
rename to tests/common/res/drawable-xhdpi/ch_476_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_477_logo.png b/tests/common/res/drawable-xhdpi/ch_477_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_477_logo.png
rename to tests/common/res/drawable-xhdpi/ch_477_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_478_logo.png b/tests/common/res/drawable-xhdpi/ch_478_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_478_logo.png
rename to tests/common/res/drawable-xhdpi/ch_478_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_479_logo.png b/tests/common/res/drawable-xhdpi/ch_479_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_479_logo.png
rename to tests/common/res/drawable-xhdpi/ch_479_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_47_logo.png b/tests/common/res/drawable-xhdpi/ch_47_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_47_logo.png
rename to tests/common/res/drawable-xhdpi/ch_47_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_480_logo.png b/tests/common/res/drawable-xhdpi/ch_480_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_480_logo.png
rename to tests/common/res/drawable-xhdpi/ch_480_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_481_logo.png b/tests/common/res/drawable-xhdpi/ch_481_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_481_logo.png
rename to tests/common/res/drawable-xhdpi/ch_481_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_482_logo.png b/tests/common/res/drawable-xhdpi/ch_482_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_482_logo.png
rename to tests/common/res/drawable-xhdpi/ch_482_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_483_logo.png b/tests/common/res/drawable-xhdpi/ch_483_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_483_logo.png
rename to tests/common/res/drawable-xhdpi/ch_483_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_484_logo.png b/tests/common/res/drawable-xhdpi/ch_484_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_484_logo.png
rename to tests/common/res/drawable-xhdpi/ch_484_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_485_logo.png b/tests/common/res/drawable-xhdpi/ch_485_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_485_logo.png
rename to tests/common/res/drawable-xhdpi/ch_485_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_486_logo.png b/tests/common/res/drawable-xhdpi/ch_486_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_486_logo.png
rename to tests/common/res/drawable-xhdpi/ch_486_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_487_logo.png b/tests/common/res/drawable-xhdpi/ch_487_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_487_logo.png
rename to tests/common/res/drawable-xhdpi/ch_487_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_488_logo.png b/tests/common/res/drawable-xhdpi/ch_488_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_488_logo.png
rename to tests/common/res/drawable-xhdpi/ch_488_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_489_logo.png b/tests/common/res/drawable-xhdpi/ch_489_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_489_logo.png
rename to tests/common/res/drawable-xhdpi/ch_489_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_48_logo.png b/tests/common/res/drawable-xhdpi/ch_48_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_48_logo.png
rename to tests/common/res/drawable-xhdpi/ch_48_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_490_logo.png b/tests/common/res/drawable-xhdpi/ch_490_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_490_logo.png
rename to tests/common/res/drawable-xhdpi/ch_490_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_491_logo.png b/tests/common/res/drawable-xhdpi/ch_491_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_491_logo.png
rename to tests/common/res/drawable-xhdpi/ch_491_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_492_logo.png b/tests/common/res/drawable-xhdpi/ch_492_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_492_logo.png
rename to tests/common/res/drawable-xhdpi/ch_492_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_493_logo.png b/tests/common/res/drawable-xhdpi/ch_493_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_493_logo.png
rename to tests/common/res/drawable-xhdpi/ch_493_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_494_logo.png b/tests/common/res/drawable-xhdpi/ch_494_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_494_logo.png
rename to tests/common/res/drawable-xhdpi/ch_494_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_495_logo.png b/tests/common/res/drawable-xhdpi/ch_495_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_495_logo.png
rename to tests/common/res/drawable-xhdpi/ch_495_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_496_logo.png b/tests/common/res/drawable-xhdpi/ch_496_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_496_logo.png
rename to tests/common/res/drawable-xhdpi/ch_496_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_497_logo.png b/tests/common/res/drawable-xhdpi/ch_497_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_497_logo.png
rename to tests/common/res/drawable-xhdpi/ch_497_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_498_logo.png b/tests/common/res/drawable-xhdpi/ch_498_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_498_logo.png
rename to tests/common/res/drawable-xhdpi/ch_498_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_499_logo.png b/tests/common/res/drawable-xhdpi/ch_499_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_499_logo.png
rename to tests/common/res/drawable-xhdpi/ch_499_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_49_logo.png b/tests/common/res/drawable-xhdpi/ch_49_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_49_logo.png
rename to tests/common/res/drawable-xhdpi/ch_49_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_4_logo.png b/tests/common/res/drawable-xhdpi/ch_4_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_4_logo.png
rename to tests/common/res/drawable-xhdpi/ch_4_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_500_logo.png b/tests/common/res/drawable-xhdpi/ch_500_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_500_logo.png
rename to tests/common/res/drawable-xhdpi/ch_500_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_501_logo.png b/tests/common/res/drawable-xhdpi/ch_501_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_501_logo.png
rename to tests/common/res/drawable-xhdpi/ch_501_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_502_logo.png b/tests/common/res/drawable-xhdpi/ch_502_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_502_logo.png
rename to tests/common/res/drawable-xhdpi/ch_502_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_503_logo.png b/tests/common/res/drawable-xhdpi/ch_503_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_503_logo.png
rename to tests/common/res/drawable-xhdpi/ch_503_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_504_logo.png b/tests/common/res/drawable-xhdpi/ch_504_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_504_logo.png
rename to tests/common/res/drawable-xhdpi/ch_504_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_505_logo.png b/tests/common/res/drawable-xhdpi/ch_505_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_505_logo.png
rename to tests/common/res/drawable-xhdpi/ch_505_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_506_logo.png b/tests/common/res/drawable-xhdpi/ch_506_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_506_logo.png
rename to tests/common/res/drawable-xhdpi/ch_506_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_507_logo.png b/tests/common/res/drawable-xhdpi/ch_507_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_507_logo.png
rename to tests/common/res/drawable-xhdpi/ch_507_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_508_logo.png b/tests/common/res/drawable-xhdpi/ch_508_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_508_logo.png
rename to tests/common/res/drawable-xhdpi/ch_508_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_509_logo.png b/tests/common/res/drawable-xhdpi/ch_509_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_509_logo.png
rename to tests/common/res/drawable-xhdpi/ch_509_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_50_logo.png b/tests/common/res/drawable-xhdpi/ch_50_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_50_logo.png
rename to tests/common/res/drawable-xhdpi/ch_50_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_510_logo.png b/tests/common/res/drawable-xhdpi/ch_510_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_510_logo.png
rename to tests/common/res/drawable-xhdpi/ch_510_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_511_logo.png b/tests/common/res/drawable-xhdpi/ch_511_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_511_logo.png
rename to tests/common/res/drawable-xhdpi/ch_511_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_512_logo.png b/tests/common/res/drawable-xhdpi/ch_512_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_512_logo.png
rename to tests/common/res/drawable-xhdpi/ch_512_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_513_logo.png b/tests/common/res/drawable-xhdpi/ch_513_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_513_logo.png
rename to tests/common/res/drawable-xhdpi/ch_513_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_514_logo.png b/tests/common/res/drawable-xhdpi/ch_514_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_514_logo.png
rename to tests/common/res/drawable-xhdpi/ch_514_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_515_logo.png b/tests/common/res/drawable-xhdpi/ch_515_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_515_logo.png
rename to tests/common/res/drawable-xhdpi/ch_515_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_516_logo.png b/tests/common/res/drawable-xhdpi/ch_516_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_516_logo.png
rename to tests/common/res/drawable-xhdpi/ch_516_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_517_logo.png b/tests/common/res/drawable-xhdpi/ch_517_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_517_logo.png
rename to tests/common/res/drawable-xhdpi/ch_517_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_518_logo.png b/tests/common/res/drawable-xhdpi/ch_518_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_518_logo.png
rename to tests/common/res/drawable-xhdpi/ch_518_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_519_logo.png b/tests/common/res/drawable-xhdpi/ch_519_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_519_logo.png
rename to tests/common/res/drawable-xhdpi/ch_519_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_51_logo.png b/tests/common/res/drawable-xhdpi/ch_51_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_51_logo.png
rename to tests/common/res/drawable-xhdpi/ch_51_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_520_logo.png b/tests/common/res/drawable-xhdpi/ch_520_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_520_logo.png
rename to tests/common/res/drawable-xhdpi/ch_520_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_521_logo.png b/tests/common/res/drawable-xhdpi/ch_521_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_521_logo.png
rename to tests/common/res/drawable-xhdpi/ch_521_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_522_logo.png b/tests/common/res/drawable-xhdpi/ch_522_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_522_logo.png
rename to tests/common/res/drawable-xhdpi/ch_522_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_523_logo.png b/tests/common/res/drawable-xhdpi/ch_523_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_523_logo.png
rename to tests/common/res/drawable-xhdpi/ch_523_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_524_logo.png b/tests/common/res/drawable-xhdpi/ch_524_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_524_logo.png
rename to tests/common/res/drawable-xhdpi/ch_524_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_525_logo.png b/tests/common/res/drawable-xhdpi/ch_525_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_525_logo.png
rename to tests/common/res/drawable-xhdpi/ch_525_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_526_logo.png b/tests/common/res/drawable-xhdpi/ch_526_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_526_logo.png
rename to tests/common/res/drawable-xhdpi/ch_526_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_527_logo.png b/tests/common/res/drawable-xhdpi/ch_527_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_527_logo.png
rename to tests/common/res/drawable-xhdpi/ch_527_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_528_logo.png b/tests/common/res/drawable-xhdpi/ch_528_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_528_logo.png
rename to tests/common/res/drawable-xhdpi/ch_528_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_529_logo.png b/tests/common/res/drawable-xhdpi/ch_529_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_529_logo.png
rename to tests/common/res/drawable-xhdpi/ch_529_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_52_logo.png b/tests/common/res/drawable-xhdpi/ch_52_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_52_logo.png
rename to tests/common/res/drawable-xhdpi/ch_52_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_530_logo.png b/tests/common/res/drawable-xhdpi/ch_530_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_530_logo.png
rename to tests/common/res/drawable-xhdpi/ch_530_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_531_logo.png b/tests/common/res/drawable-xhdpi/ch_531_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_531_logo.png
rename to tests/common/res/drawable-xhdpi/ch_531_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_532_logo.png b/tests/common/res/drawable-xhdpi/ch_532_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_532_logo.png
rename to tests/common/res/drawable-xhdpi/ch_532_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_533_logo.png b/tests/common/res/drawable-xhdpi/ch_533_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_533_logo.png
rename to tests/common/res/drawable-xhdpi/ch_533_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_534_logo.png b/tests/common/res/drawable-xhdpi/ch_534_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_534_logo.png
rename to tests/common/res/drawable-xhdpi/ch_534_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_535_logo.png b/tests/common/res/drawable-xhdpi/ch_535_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_535_logo.png
rename to tests/common/res/drawable-xhdpi/ch_535_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_536_logo.png b/tests/common/res/drawable-xhdpi/ch_536_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_536_logo.png
rename to tests/common/res/drawable-xhdpi/ch_536_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_537_logo.png b/tests/common/res/drawable-xhdpi/ch_537_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_537_logo.png
rename to tests/common/res/drawable-xhdpi/ch_537_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_538_logo.png b/tests/common/res/drawable-xhdpi/ch_538_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_538_logo.png
rename to tests/common/res/drawable-xhdpi/ch_538_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_539_logo.png b/tests/common/res/drawable-xhdpi/ch_539_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_539_logo.png
rename to tests/common/res/drawable-xhdpi/ch_539_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_53_logo.png b/tests/common/res/drawable-xhdpi/ch_53_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_53_logo.png
rename to tests/common/res/drawable-xhdpi/ch_53_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_540_logo.png b/tests/common/res/drawable-xhdpi/ch_540_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_540_logo.png
rename to tests/common/res/drawable-xhdpi/ch_540_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_541_logo.png b/tests/common/res/drawable-xhdpi/ch_541_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_541_logo.png
rename to tests/common/res/drawable-xhdpi/ch_541_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_542_logo.png b/tests/common/res/drawable-xhdpi/ch_542_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_542_logo.png
rename to tests/common/res/drawable-xhdpi/ch_542_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_543_logo.png b/tests/common/res/drawable-xhdpi/ch_543_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_543_logo.png
rename to tests/common/res/drawable-xhdpi/ch_543_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_544_logo.png b/tests/common/res/drawable-xhdpi/ch_544_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_544_logo.png
rename to tests/common/res/drawable-xhdpi/ch_544_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_545_logo.png b/tests/common/res/drawable-xhdpi/ch_545_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_545_logo.png
rename to tests/common/res/drawable-xhdpi/ch_545_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_546_logo.png b/tests/common/res/drawable-xhdpi/ch_546_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_546_logo.png
rename to tests/common/res/drawable-xhdpi/ch_546_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_547_logo.png b/tests/common/res/drawable-xhdpi/ch_547_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_547_logo.png
rename to tests/common/res/drawable-xhdpi/ch_547_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_548_logo.png b/tests/common/res/drawable-xhdpi/ch_548_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_548_logo.png
rename to tests/common/res/drawable-xhdpi/ch_548_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_549_logo.png b/tests/common/res/drawable-xhdpi/ch_549_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_549_logo.png
rename to tests/common/res/drawable-xhdpi/ch_549_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_54_logo.png b/tests/common/res/drawable-xhdpi/ch_54_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_54_logo.png
rename to tests/common/res/drawable-xhdpi/ch_54_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_550_logo.png b/tests/common/res/drawable-xhdpi/ch_550_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_550_logo.png
rename to tests/common/res/drawable-xhdpi/ch_550_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_551_logo.png b/tests/common/res/drawable-xhdpi/ch_551_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_551_logo.png
rename to tests/common/res/drawable-xhdpi/ch_551_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_552_logo.png b/tests/common/res/drawable-xhdpi/ch_552_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_552_logo.png
rename to tests/common/res/drawable-xhdpi/ch_552_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_553_logo.png b/tests/common/res/drawable-xhdpi/ch_553_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_553_logo.png
rename to tests/common/res/drawable-xhdpi/ch_553_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_554_logo.png b/tests/common/res/drawable-xhdpi/ch_554_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_554_logo.png
rename to tests/common/res/drawable-xhdpi/ch_554_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_555_logo.png b/tests/common/res/drawable-xhdpi/ch_555_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_555_logo.png
rename to tests/common/res/drawable-xhdpi/ch_555_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_556_logo.png b/tests/common/res/drawable-xhdpi/ch_556_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_556_logo.png
rename to tests/common/res/drawable-xhdpi/ch_556_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_557_logo.png b/tests/common/res/drawable-xhdpi/ch_557_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_557_logo.png
rename to tests/common/res/drawable-xhdpi/ch_557_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_558_logo.png b/tests/common/res/drawable-xhdpi/ch_558_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_558_logo.png
rename to tests/common/res/drawable-xhdpi/ch_558_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_559_logo.png b/tests/common/res/drawable-xhdpi/ch_559_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_559_logo.png
rename to tests/common/res/drawable-xhdpi/ch_559_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_55_logo.png b/tests/common/res/drawable-xhdpi/ch_55_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_55_logo.png
rename to tests/common/res/drawable-xhdpi/ch_55_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_560_logo.png b/tests/common/res/drawable-xhdpi/ch_560_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_560_logo.png
rename to tests/common/res/drawable-xhdpi/ch_560_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_561_logo.png b/tests/common/res/drawable-xhdpi/ch_561_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_561_logo.png
rename to tests/common/res/drawable-xhdpi/ch_561_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_562_logo.png b/tests/common/res/drawable-xhdpi/ch_562_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_562_logo.png
rename to tests/common/res/drawable-xhdpi/ch_562_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_563_logo.png b/tests/common/res/drawable-xhdpi/ch_563_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_563_logo.png
rename to tests/common/res/drawable-xhdpi/ch_563_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_564_logo.png b/tests/common/res/drawable-xhdpi/ch_564_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_564_logo.png
rename to tests/common/res/drawable-xhdpi/ch_564_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_565_logo.png b/tests/common/res/drawable-xhdpi/ch_565_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_565_logo.png
rename to tests/common/res/drawable-xhdpi/ch_565_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_566_logo.png b/tests/common/res/drawable-xhdpi/ch_566_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_566_logo.png
rename to tests/common/res/drawable-xhdpi/ch_566_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_567_logo.png b/tests/common/res/drawable-xhdpi/ch_567_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_567_logo.png
rename to tests/common/res/drawable-xhdpi/ch_567_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_568_logo.png b/tests/common/res/drawable-xhdpi/ch_568_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_568_logo.png
rename to tests/common/res/drawable-xhdpi/ch_568_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_569_logo.png b/tests/common/res/drawable-xhdpi/ch_569_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_569_logo.png
rename to tests/common/res/drawable-xhdpi/ch_569_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_56_logo.png b/tests/common/res/drawable-xhdpi/ch_56_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_56_logo.png
rename to tests/common/res/drawable-xhdpi/ch_56_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_570_logo.png b/tests/common/res/drawable-xhdpi/ch_570_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_570_logo.png
rename to tests/common/res/drawable-xhdpi/ch_570_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_571_logo.png b/tests/common/res/drawable-xhdpi/ch_571_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_571_logo.png
rename to tests/common/res/drawable-xhdpi/ch_571_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_572_logo.png b/tests/common/res/drawable-xhdpi/ch_572_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_572_logo.png
rename to tests/common/res/drawable-xhdpi/ch_572_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_573_logo.png b/tests/common/res/drawable-xhdpi/ch_573_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_573_logo.png
rename to tests/common/res/drawable-xhdpi/ch_573_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_574_logo.png b/tests/common/res/drawable-xhdpi/ch_574_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_574_logo.png
rename to tests/common/res/drawable-xhdpi/ch_574_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_575_logo.png b/tests/common/res/drawable-xhdpi/ch_575_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_575_logo.png
rename to tests/common/res/drawable-xhdpi/ch_575_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_576_logo.png b/tests/common/res/drawable-xhdpi/ch_576_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_576_logo.png
rename to tests/common/res/drawable-xhdpi/ch_576_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_577_logo.png b/tests/common/res/drawable-xhdpi/ch_577_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_577_logo.png
rename to tests/common/res/drawable-xhdpi/ch_577_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_578_logo.png b/tests/common/res/drawable-xhdpi/ch_578_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_578_logo.png
rename to tests/common/res/drawable-xhdpi/ch_578_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_579_logo.png b/tests/common/res/drawable-xhdpi/ch_579_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_579_logo.png
rename to tests/common/res/drawable-xhdpi/ch_579_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_57_logo.png b/tests/common/res/drawable-xhdpi/ch_57_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_57_logo.png
rename to tests/common/res/drawable-xhdpi/ch_57_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_580_logo.png b/tests/common/res/drawable-xhdpi/ch_580_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_580_logo.png
rename to tests/common/res/drawable-xhdpi/ch_580_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_581_logo.png b/tests/common/res/drawable-xhdpi/ch_581_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_581_logo.png
rename to tests/common/res/drawable-xhdpi/ch_581_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_582_logo.png b/tests/common/res/drawable-xhdpi/ch_582_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_582_logo.png
rename to tests/common/res/drawable-xhdpi/ch_582_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_583_logo.png b/tests/common/res/drawable-xhdpi/ch_583_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_583_logo.png
rename to tests/common/res/drawable-xhdpi/ch_583_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_584_logo.png b/tests/common/res/drawable-xhdpi/ch_584_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_584_logo.png
rename to tests/common/res/drawable-xhdpi/ch_584_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_585_logo.png b/tests/common/res/drawable-xhdpi/ch_585_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_585_logo.png
rename to tests/common/res/drawable-xhdpi/ch_585_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_586_logo.png b/tests/common/res/drawable-xhdpi/ch_586_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_586_logo.png
rename to tests/common/res/drawable-xhdpi/ch_586_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_587_logo.png b/tests/common/res/drawable-xhdpi/ch_587_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_587_logo.png
rename to tests/common/res/drawable-xhdpi/ch_587_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_588_logo.png b/tests/common/res/drawable-xhdpi/ch_588_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_588_logo.png
rename to tests/common/res/drawable-xhdpi/ch_588_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_589_logo.png b/tests/common/res/drawable-xhdpi/ch_589_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_589_logo.png
rename to tests/common/res/drawable-xhdpi/ch_589_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_58_logo.png b/tests/common/res/drawable-xhdpi/ch_58_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_58_logo.png
rename to tests/common/res/drawable-xhdpi/ch_58_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_590_logo.png b/tests/common/res/drawable-xhdpi/ch_590_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_590_logo.png
rename to tests/common/res/drawable-xhdpi/ch_590_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_591_logo.png b/tests/common/res/drawable-xhdpi/ch_591_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_591_logo.png
rename to tests/common/res/drawable-xhdpi/ch_591_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_592_logo.png b/tests/common/res/drawable-xhdpi/ch_592_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_592_logo.png
rename to tests/common/res/drawable-xhdpi/ch_592_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_593_logo.png b/tests/common/res/drawable-xhdpi/ch_593_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_593_logo.png
rename to tests/common/res/drawable-xhdpi/ch_593_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_594_logo.png b/tests/common/res/drawable-xhdpi/ch_594_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_594_logo.png
rename to tests/common/res/drawable-xhdpi/ch_594_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_595_logo.png b/tests/common/res/drawable-xhdpi/ch_595_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_595_logo.png
rename to tests/common/res/drawable-xhdpi/ch_595_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_596_logo.png b/tests/common/res/drawable-xhdpi/ch_596_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_596_logo.png
rename to tests/common/res/drawable-xhdpi/ch_596_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_597_logo.png b/tests/common/res/drawable-xhdpi/ch_597_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_597_logo.png
rename to tests/common/res/drawable-xhdpi/ch_597_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_598_logo.png b/tests/common/res/drawable-xhdpi/ch_598_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_598_logo.png
rename to tests/common/res/drawable-xhdpi/ch_598_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_599_logo.png b/tests/common/res/drawable-xhdpi/ch_599_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_599_logo.png
rename to tests/common/res/drawable-xhdpi/ch_599_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_59_logo.png b/tests/common/res/drawable-xhdpi/ch_59_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_59_logo.png
rename to tests/common/res/drawable-xhdpi/ch_59_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_5_logo.png b/tests/common/res/drawable-xhdpi/ch_5_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_5_logo.png
rename to tests/common/res/drawable-xhdpi/ch_5_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_600_logo.png b/tests/common/res/drawable-xhdpi/ch_600_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_600_logo.png
rename to tests/common/res/drawable-xhdpi/ch_600_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_601_logo.png b/tests/common/res/drawable-xhdpi/ch_601_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_601_logo.png
rename to tests/common/res/drawable-xhdpi/ch_601_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_602_logo.png b/tests/common/res/drawable-xhdpi/ch_602_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_602_logo.png
rename to tests/common/res/drawable-xhdpi/ch_602_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_603_logo.png b/tests/common/res/drawable-xhdpi/ch_603_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_603_logo.png
rename to tests/common/res/drawable-xhdpi/ch_603_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_604_logo.png b/tests/common/res/drawable-xhdpi/ch_604_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_604_logo.png
rename to tests/common/res/drawable-xhdpi/ch_604_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_605_logo.png b/tests/common/res/drawable-xhdpi/ch_605_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_605_logo.png
rename to tests/common/res/drawable-xhdpi/ch_605_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_606_logo.png b/tests/common/res/drawable-xhdpi/ch_606_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_606_logo.png
rename to tests/common/res/drawable-xhdpi/ch_606_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_607_logo.png b/tests/common/res/drawable-xhdpi/ch_607_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_607_logo.png
rename to tests/common/res/drawable-xhdpi/ch_607_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_608_logo.png b/tests/common/res/drawable-xhdpi/ch_608_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_608_logo.png
rename to tests/common/res/drawable-xhdpi/ch_608_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_609_logo.png b/tests/common/res/drawable-xhdpi/ch_609_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_609_logo.png
rename to tests/common/res/drawable-xhdpi/ch_609_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_60_logo.png b/tests/common/res/drawable-xhdpi/ch_60_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_60_logo.png
rename to tests/common/res/drawable-xhdpi/ch_60_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_610_logo.png b/tests/common/res/drawable-xhdpi/ch_610_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_610_logo.png
rename to tests/common/res/drawable-xhdpi/ch_610_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_611_logo.png b/tests/common/res/drawable-xhdpi/ch_611_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_611_logo.png
rename to tests/common/res/drawable-xhdpi/ch_611_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_612_logo.png b/tests/common/res/drawable-xhdpi/ch_612_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_612_logo.png
rename to tests/common/res/drawable-xhdpi/ch_612_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_613_logo.png b/tests/common/res/drawable-xhdpi/ch_613_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_613_logo.png
rename to tests/common/res/drawable-xhdpi/ch_613_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_614_logo.png b/tests/common/res/drawable-xhdpi/ch_614_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_614_logo.png
rename to tests/common/res/drawable-xhdpi/ch_614_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_615_logo.png b/tests/common/res/drawable-xhdpi/ch_615_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_615_logo.png
rename to tests/common/res/drawable-xhdpi/ch_615_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_616_logo.png b/tests/common/res/drawable-xhdpi/ch_616_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_616_logo.png
rename to tests/common/res/drawable-xhdpi/ch_616_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_617_logo.png b/tests/common/res/drawable-xhdpi/ch_617_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_617_logo.png
rename to tests/common/res/drawable-xhdpi/ch_617_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_618_logo.png b/tests/common/res/drawable-xhdpi/ch_618_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_618_logo.png
rename to tests/common/res/drawable-xhdpi/ch_618_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_619_logo.png b/tests/common/res/drawable-xhdpi/ch_619_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_619_logo.png
rename to tests/common/res/drawable-xhdpi/ch_619_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_61_logo.png b/tests/common/res/drawable-xhdpi/ch_61_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_61_logo.png
rename to tests/common/res/drawable-xhdpi/ch_61_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_620_logo.png b/tests/common/res/drawable-xhdpi/ch_620_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_620_logo.png
rename to tests/common/res/drawable-xhdpi/ch_620_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_621_logo.png b/tests/common/res/drawable-xhdpi/ch_621_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_621_logo.png
rename to tests/common/res/drawable-xhdpi/ch_621_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_622_logo.png b/tests/common/res/drawable-xhdpi/ch_622_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_622_logo.png
rename to tests/common/res/drawable-xhdpi/ch_622_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_623_logo.png b/tests/common/res/drawable-xhdpi/ch_623_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_623_logo.png
rename to tests/common/res/drawable-xhdpi/ch_623_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_624_logo.png b/tests/common/res/drawable-xhdpi/ch_624_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_624_logo.png
rename to tests/common/res/drawable-xhdpi/ch_624_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_625_logo.png b/tests/common/res/drawable-xhdpi/ch_625_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_625_logo.png
rename to tests/common/res/drawable-xhdpi/ch_625_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_626_logo.png b/tests/common/res/drawable-xhdpi/ch_626_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_626_logo.png
rename to tests/common/res/drawable-xhdpi/ch_626_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_627_logo.png b/tests/common/res/drawable-xhdpi/ch_627_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_627_logo.png
rename to tests/common/res/drawable-xhdpi/ch_627_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_628_logo.png b/tests/common/res/drawable-xhdpi/ch_628_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_628_logo.png
rename to tests/common/res/drawable-xhdpi/ch_628_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_629_logo.png b/tests/common/res/drawable-xhdpi/ch_629_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_629_logo.png
rename to tests/common/res/drawable-xhdpi/ch_629_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_62_logo.png b/tests/common/res/drawable-xhdpi/ch_62_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_62_logo.png
rename to tests/common/res/drawable-xhdpi/ch_62_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_630_logo.png b/tests/common/res/drawable-xhdpi/ch_630_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_630_logo.png
rename to tests/common/res/drawable-xhdpi/ch_630_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_631_logo.png b/tests/common/res/drawable-xhdpi/ch_631_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_631_logo.png
rename to tests/common/res/drawable-xhdpi/ch_631_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_632_logo.png b/tests/common/res/drawable-xhdpi/ch_632_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_632_logo.png
rename to tests/common/res/drawable-xhdpi/ch_632_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_633_logo.png b/tests/common/res/drawable-xhdpi/ch_633_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_633_logo.png
rename to tests/common/res/drawable-xhdpi/ch_633_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_634_logo.png b/tests/common/res/drawable-xhdpi/ch_634_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_634_logo.png
rename to tests/common/res/drawable-xhdpi/ch_634_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_635_logo.png b/tests/common/res/drawable-xhdpi/ch_635_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_635_logo.png
rename to tests/common/res/drawable-xhdpi/ch_635_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_636_logo.png b/tests/common/res/drawable-xhdpi/ch_636_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_636_logo.png
rename to tests/common/res/drawable-xhdpi/ch_636_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_637_logo.png b/tests/common/res/drawable-xhdpi/ch_637_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_637_logo.png
rename to tests/common/res/drawable-xhdpi/ch_637_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_638_logo.png b/tests/common/res/drawable-xhdpi/ch_638_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_638_logo.png
rename to tests/common/res/drawable-xhdpi/ch_638_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_639_logo.png b/tests/common/res/drawable-xhdpi/ch_639_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_639_logo.png
rename to tests/common/res/drawable-xhdpi/ch_639_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_63_logo.png b/tests/common/res/drawable-xhdpi/ch_63_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_63_logo.png
rename to tests/common/res/drawable-xhdpi/ch_63_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_640_logo.png b/tests/common/res/drawable-xhdpi/ch_640_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_640_logo.png
rename to tests/common/res/drawable-xhdpi/ch_640_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_641_logo.png b/tests/common/res/drawable-xhdpi/ch_641_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_641_logo.png
rename to tests/common/res/drawable-xhdpi/ch_641_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_642_logo.png b/tests/common/res/drawable-xhdpi/ch_642_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_642_logo.png
rename to tests/common/res/drawable-xhdpi/ch_642_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_643_logo.png b/tests/common/res/drawable-xhdpi/ch_643_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_643_logo.png
rename to tests/common/res/drawable-xhdpi/ch_643_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_644_logo.png b/tests/common/res/drawable-xhdpi/ch_644_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_644_logo.png
rename to tests/common/res/drawable-xhdpi/ch_644_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_645_logo.png b/tests/common/res/drawable-xhdpi/ch_645_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_645_logo.png
rename to tests/common/res/drawable-xhdpi/ch_645_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_646_logo.png b/tests/common/res/drawable-xhdpi/ch_646_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_646_logo.png
rename to tests/common/res/drawable-xhdpi/ch_646_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_647_logo.png b/tests/common/res/drawable-xhdpi/ch_647_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_647_logo.png
rename to tests/common/res/drawable-xhdpi/ch_647_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_648_logo.png b/tests/common/res/drawable-xhdpi/ch_648_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_648_logo.png
rename to tests/common/res/drawable-xhdpi/ch_648_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_649_logo.png b/tests/common/res/drawable-xhdpi/ch_649_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_649_logo.png
rename to tests/common/res/drawable-xhdpi/ch_649_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_64_logo.png b/tests/common/res/drawable-xhdpi/ch_64_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_64_logo.png
rename to tests/common/res/drawable-xhdpi/ch_64_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_650_logo.png b/tests/common/res/drawable-xhdpi/ch_650_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_650_logo.png
rename to tests/common/res/drawable-xhdpi/ch_650_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_651_logo.png b/tests/common/res/drawable-xhdpi/ch_651_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_651_logo.png
rename to tests/common/res/drawable-xhdpi/ch_651_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_652_logo.png b/tests/common/res/drawable-xhdpi/ch_652_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_652_logo.png
rename to tests/common/res/drawable-xhdpi/ch_652_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_653_logo.png b/tests/common/res/drawable-xhdpi/ch_653_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_653_logo.png
rename to tests/common/res/drawable-xhdpi/ch_653_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_654_logo.png b/tests/common/res/drawable-xhdpi/ch_654_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_654_logo.png
rename to tests/common/res/drawable-xhdpi/ch_654_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_655_logo.png b/tests/common/res/drawable-xhdpi/ch_655_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_655_logo.png
rename to tests/common/res/drawable-xhdpi/ch_655_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_656_logo.png b/tests/common/res/drawable-xhdpi/ch_656_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_656_logo.png
rename to tests/common/res/drawable-xhdpi/ch_656_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_657_logo.png b/tests/common/res/drawable-xhdpi/ch_657_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_657_logo.png
rename to tests/common/res/drawable-xhdpi/ch_657_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_658_logo.png b/tests/common/res/drawable-xhdpi/ch_658_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_658_logo.png
rename to tests/common/res/drawable-xhdpi/ch_658_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_659_logo.png b/tests/common/res/drawable-xhdpi/ch_659_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_659_logo.png
rename to tests/common/res/drawable-xhdpi/ch_659_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_65_logo.png b/tests/common/res/drawable-xhdpi/ch_65_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_65_logo.png
rename to tests/common/res/drawable-xhdpi/ch_65_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_660_logo.png b/tests/common/res/drawable-xhdpi/ch_660_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_660_logo.png
rename to tests/common/res/drawable-xhdpi/ch_660_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_661_logo.png b/tests/common/res/drawable-xhdpi/ch_661_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_661_logo.png
rename to tests/common/res/drawable-xhdpi/ch_661_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_662_logo.png b/tests/common/res/drawable-xhdpi/ch_662_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_662_logo.png
rename to tests/common/res/drawable-xhdpi/ch_662_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_663_logo.png b/tests/common/res/drawable-xhdpi/ch_663_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_663_logo.png
rename to tests/common/res/drawable-xhdpi/ch_663_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_664_logo.png b/tests/common/res/drawable-xhdpi/ch_664_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_664_logo.png
rename to tests/common/res/drawable-xhdpi/ch_664_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_665_logo.png b/tests/common/res/drawable-xhdpi/ch_665_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_665_logo.png
rename to tests/common/res/drawable-xhdpi/ch_665_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_666_logo.png b/tests/common/res/drawable-xhdpi/ch_666_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_666_logo.png
rename to tests/common/res/drawable-xhdpi/ch_666_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_667_logo.png b/tests/common/res/drawable-xhdpi/ch_667_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_667_logo.png
rename to tests/common/res/drawable-xhdpi/ch_667_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_668_logo.png b/tests/common/res/drawable-xhdpi/ch_668_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_668_logo.png
rename to tests/common/res/drawable-xhdpi/ch_668_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_669_logo.png b/tests/common/res/drawable-xhdpi/ch_669_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_669_logo.png
rename to tests/common/res/drawable-xhdpi/ch_669_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_66_logo.png b/tests/common/res/drawable-xhdpi/ch_66_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_66_logo.png
rename to tests/common/res/drawable-xhdpi/ch_66_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_670_logo.png b/tests/common/res/drawable-xhdpi/ch_670_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_670_logo.png
rename to tests/common/res/drawable-xhdpi/ch_670_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_671_logo.png b/tests/common/res/drawable-xhdpi/ch_671_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_671_logo.png
rename to tests/common/res/drawable-xhdpi/ch_671_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_672_logo.png b/tests/common/res/drawable-xhdpi/ch_672_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_672_logo.png
rename to tests/common/res/drawable-xhdpi/ch_672_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_673_logo.png b/tests/common/res/drawable-xhdpi/ch_673_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_673_logo.png
rename to tests/common/res/drawable-xhdpi/ch_673_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_674_logo.png b/tests/common/res/drawable-xhdpi/ch_674_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_674_logo.png
rename to tests/common/res/drawable-xhdpi/ch_674_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_675_logo.png b/tests/common/res/drawable-xhdpi/ch_675_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_675_logo.png
rename to tests/common/res/drawable-xhdpi/ch_675_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_676_logo.png b/tests/common/res/drawable-xhdpi/ch_676_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_676_logo.png
rename to tests/common/res/drawable-xhdpi/ch_676_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_677_logo.png b/tests/common/res/drawable-xhdpi/ch_677_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_677_logo.png
rename to tests/common/res/drawable-xhdpi/ch_677_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_678_logo.png b/tests/common/res/drawable-xhdpi/ch_678_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_678_logo.png
rename to tests/common/res/drawable-xhdpi/ch_678_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_679_logo.png b/tests/common/res/drawable-xhdpi/ch_679_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_679_logo.png
rename to tests/common/res/drawable-xhdpi/ch_679_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_67_logo.png b/tests/common/res/drawable-xhdpi/ch_67_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_67_logo.png
rename to tests/common/res/drawable-xhdpi/ch_67_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_680_logo.png b/tests/common/res/drawable-xhdpi/ch_680_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_680_logo.png
rename to tests/common/res/drawable-xhdpi/ch_680_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_681_logo.png b/tests/common/res/drawable-xhdpi/ch_681_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_681_logo.png
rename to tests/common/res/drawable-xhdpi/ch_681_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_682_logo.png b/tests/common/res/drawable-xhdpi/ch_682_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_682_logo.png
rename to tests/common/res/drawable-xhdpi/ch_682_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_683_logo.png b/tests/common/res/drawable-xhdpi/ch_683_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_683_logo.png
rename to tests/common/res/drawable-xhdpi/ch_683_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_684_logo.png b/tests/common/res/drawable-xhdpi/ch_684_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_684_logo.png
rename to tests/common/res/drawable-xhdpi/ch_684_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_685_logo.png b/tests/common/res/drawable-xhdpi/ch_685_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_685_logo.png
rename to tests/common/res/drawable-xhdpi/ch_685_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_686_logo.png b/tests/common/res/drawable-xhdpi/ch_686_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_686_logo.png
rename to tests/common/res/drawable-xhdpi/ch_686_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_687_logo.png b/tests/common/res/drawable-xhdpi/ch_687_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_687_logo.png
rename to tests/common/res/drawable-xhdpi/ch_687_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_688_logo.png b/tests/common/res/drawable-xhdpi/ch_688_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_688_logo.png
rename to tests/common/res/drawable-xhdpi/ch_688_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_689_logo.png b/tests/common/res/drawable-xhdpi/ch_689_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_689_logo.png
rename to tests/common/res/drawable-xhdpi/ch_689_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_68_logo.png b/tests/common/res/drawable-xhdpi/ch_68_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_68_logo.png
rename to tests/common/res/drawable-xhdpi/ch_68_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_690_logo.png b/tests/common/res/drawable-xhdpi/ch_690_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_690_logo.png
rename to tests/common/res/drawable-xhdpi/ch_690_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_691_logo.png b/tests/common/res/drawable-xhdpi/ch_691_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_691_logo.png
rename to tests/common/res/drawable-xhdpi/ch_691_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_692_logo.png b/tests/common/res/drawable-xhdpi/ch_692_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_692_logo.png
rename to tests/common/res/drawable-xhdpi/ch_692_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_693_logo.png b/tests/common/res/drawable-xhdpi/ch_693_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_693_logo.png
rename to tests/common/res/drawable-xhdpi/ch_693_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_694_logo.png b/tests/common/res/drawable-xhdpi/ch_694_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_694_logo.png
rename to tests/common/res/drawable-xhdpi/ch_694_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_695_logo.png b/tests/common/res/drawable-xhdpi/ch_695_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_695_logo.png
rename to tests/common/res/drawable-xhdpi/ch_695_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_696_logo.png b/tests/common/res/drawable-xhdpi/ch_696_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_696_logo.png
rename to tests/common/res/drawable-xhdpi/ch_696_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_697_logo.png b/tests/common/res/drawable-xhdpi/ch_697_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_697_logo.png
rename to tests/common/res/drawable-xhdpi/ch_697_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_698_logo.png b/tests/common/res/drawable-xhdpi/ch_698_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_698_logo.png
rename to tests/common/res/drawable-xhdpi/ch_698_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_699_logo.png b/tests/common/res/drawable-xhdpi/ch_699_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_699_logo.png
rename to tests/common/res/drawable-xhdpi/ch_699_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_69_logo.png b/tests/common/res/drawable-xhdpi/ch_69_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_69_logo.png
rename to tests/common/res/drawable-xhdpi/ch_69_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_6_logo.png b/tests/common/res/drawable-xhdpi/ch_6_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_6_logo.png
rename to tests/common/res/drawable-xhdpi/ch_6_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_700_logo.png b/tests/common/res/drawable-xhdpi/ch_700_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_700_logo.png
rename to tests/common/res/drawable-xhdpi/ch_700_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_701_logo.png b/tests/common/res/drawable-xhdpi/ch_701_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_701_logo.png
rename to tests/common/res/drawable-xhdpi/ch_701_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_702_logo.png b/tests/common/res/drawable-xhdpi/ch_702_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_702_logo.png
rename to tests/common/res/drawable-xhdpi/ch_702_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_703_logo.png b/tests/common/res/drawable-xhdpi/ch_703_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_703_logo.png
rename to tests/common/res/drawable-xhdpi/ch_703_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_704_logo.png b/tests/common/res/drawable-xhdpi/ch_704_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_704_logo.png
rename to tests/common/res/drawable-xhdpi/ch_704_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_705_logo.png b/tests/common/res/drawable-xhdpi/ch_705_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_705_logo.png
rename to tests/common/res/drawable-xhdpi/ch_705_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_706_logo.png b/tests/common/res/drawable-xhdpi/ch_706_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_706_logo.png
rename to tests/common/res/drawable-xhdpi/ch_706_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_707_logo.png b/tests/common/res/drawable-xhdpi/ch_707_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_707_logo.png
rename to tests/common/res/drawable-xhdpi/ch_707_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_708_logo.png b/tests/common/res/drawable-xhdpi/ch_708_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_708_logo.png
rename to tests/common/res/drawable-xhdpi/ch_708_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_709_logo.png b/tests/common/res/drawable-xhdpi/ch_709_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_709_logo.png
rename to tests/common/res/drawable-xhdpi/ch_709_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_70_logo.png b/tests/common/res/drawable-xhdpi/ch_70_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_70_logo.png
rename to tests/common/res/drawable-xhdpi/ch_70_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_710_logo.png b/tests/common/res/drawable-xhdpi/ch_710_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_710_logo.png
rename to tests/common/res/drawable-xhdpi/ch_710_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_711_logo.png b/tests/common/res/drawable-xhdpi/ch_711_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_711_logo.png
rename to tests/common/res/drawable-xhdpi/ch_711_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_712_logo.png b/tests/common/res/drawable-xhdpi/ch_712_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_712_logo.png
rename to tests/common/res/drawable-xhdpi/ch_712_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_713_logo.png b/tests/common/res/drawable-xhdpi/ch_713_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_713_logo.png
rename to tests/common/res/drawable-xhdpi/ch_713_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_714_logo.png b/tests/common/res/drawable-xhdpi/ch_714_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_714_logo.png
rename to tests/common/res/drawable-xhdpi/ch_714_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_715_logo.png b/tests/common/res/drawable-xhdpi/ch_715_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_715_logo.png
rename to tests/common/res/drawable-xhdpi/ch_715_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_716_logo.png b/tests/common/res/drawable-xhdpi/ch_716_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_716_logo.png
rename to tests/common/res/drawable-xhdpi/ch_716_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_717_logo.png b/tests/common/res/drawable-xhdpi/ch_717_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_717_logo.png
rename to tests/common/res/drawable-xhdpi/ch_717_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_718_logo.png b/tests/common/res/drawable-xhdpi/ch_718_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_718_logo.png
rename to tests/common/res/drawable-xhdpi/ch_718_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_719_logo.png b/tests/common/res/drawable-xhdpi/ch_719_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_719_logo.png
rename to tests/common/res/drawable-xhdpi/ch_719_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_71_logo.png b/tests/common/res/drawable-xhdpi/ch_71_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_71_logo.png
rename to tests/common/res/drawable-xhdpi/ch_71_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_720_logo.png b/tests/common/res/drawable-xhdpi/ch_720_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_720_logo.png
rename to tests/common/res/drawable-xhdpi/ch_720_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_721_logo.png b/tests/common/res/drawable-xhdpi/ch_721_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_721_logo.png
rename to tests/common/res/drawable-xhdpi/ch_721_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_722_logo.png b/tests/common/res/drawable-xhdpi/ch_722_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_722_logo.png
rename to tests/common/res/drawable-xhdpi/ch_722_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_723_logo.png b/tests/common/res/drawable-xhdpi/ch_723_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_723_logo.png
rename to tests/common/res/drawable-xhdpi/ch_723_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_724_logo.png b/tests/common/res/drawable-xhdpi/ch_724_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_724_logo.png
rename to tests/common/res/drawable-xhdpi/ch_724_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_725_logo.png b/tests/common/res/drawable-xhdpi/ch_725_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_725_logo.png
rename to tests/common/res/drawable-xhdpi/ch_725_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_726_logo.png b/tests/common/res/drawable-xhdpi/ch_726_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_726_logo.png
rename to tests/common/res/drawable-xhdpi/ch_726_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_727_logo.png b/tests/common/res/drawable-xhdpi/ch_727_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_727_logo.png
rename to tests/common/res/drawable-xhdpi/ch_727_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_728_logo.png b/tests/common/res/drawable-xhdpi/ch_728_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_728_logo.png
rename to tests/common/res/drawable-xhdpi/ch_728_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_729_logo.png b/tests/common/res/drawable-xhdpi/ch_729_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_729_logo.png
rename to tests/common/res/drawable-xhdpi/ch_729_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_72_logo.png b/tests/common/res/drawable-xhdpi/ch_72_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_72_logo.png
rename to tests/common/res/drawable-xhdpi/ch_72_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_730_logo.png b/tests/common/res/drawable-xhdpi/ch_730_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_730_logo.png
rename to tests/common/res/drawable-xhdpi/ch_730_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_731_logo.png b/tests/common/res/drawable-xhdpi/ch_731_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_731_logo.png
rename to tests/common/res/drawable-xhdpi/ch_731_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_732_logo.png b/tests/common/res/drawable-xhdpi/ch_732_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_732_logo.png
rename to tests/common/res/drawable-xhdpi/ch_732_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_733_logo.png b/tests/common/res/drawable-xhdpi/ch_733_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_733_logo.png
rename to tests/common/res/drawable-xhdpi/ch_733_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_734_logo.png b/tests/common/res/drawable-xhdpi/ch_734_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_734_logo.png
rename to tests/common/res/drawable-xhdpi/ch_734_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_735_logo.png b/tests/common/res/drawable-xhdpi/ch_735_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_735_logo.png
rename to tests/common/res/drawable-xhdpi/ch_735_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_736_logo.png b/tests/common/res/drawable-xhdpi/ch_736_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_736_logo.png
rename to tests/common/res/drawable-xhdpi/ch_736_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_737_logo.png b/tests/common/res/drawable-xhdpi/ch_737_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_737_logo.png
rename to tests/common/res/drawable-xhdpi/ch_737_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_738_logo.png b/tests/common/res/drawable-xhdpi/ch_738_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_738_logo.png
rename to tests/common/res/drawable-xhdpi/ch_738_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_739_logo.png b/tests/common/res/drawable-xhdpi/ch_739_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_739_logo.png
rename to tests/common/res/drawable-xhdpi/ch_739_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_73_logo.png b/tests/common/res/drawable-xhdpi/ch_73_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_73_logo.png
rename to tests/common/res/drawable-xhdpi/ch_73_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_740_logo.png b/tests/common/res/drawable-xhdpi/ch_740_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_740_logo.png
rename to tests/common/res/drawable-xhdpi/ch_740_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_741_logo.png b/tests/common/res/drawable-xhdpi/ch_741_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_741_logo.png
rename to tests/common/res/drawable-xhdpi/ch_741_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_742_logo.png b/tests/common/res/drawable-xhdpi/ch_742_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_742_logo.png
rename to tests/common/res/drawable-xhdpi/ch_742_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_743_logo.png b/tests/common/res/drawable-xhdpi/ch_743_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_743_logo.png
rename to tests/common/res/drawable-xhdpi/ch_743_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_744_logo.png b/tests/common/res/drawable-xhdpi/ch_744_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_744_logo.png
rename to tests/common/res/drawable-xhdpi/ch_744_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_745_logo.png b/tests/common/res/drawable-xhdpi/ch_745_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_745_logo.png
rename to tests/common/res/drawable-xhdpi/ch_745_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_746_logo.png b/tests/common/res/drawable-xhdpi/ch_746_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_746_logo.png
rename to tests/common/res/drawable-xhdpi/ch_746_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_747_logo.png b/tests/common/res/drawable-xhdpi/ch_747_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_747_logo.png
rename to tests/common/res/drawable-xhdpi/ch_747_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_748_logo.png b/tests/common/res/drawable-xhdpi/ch_748_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_748_logo.png
rename to tests/common/res/drawable-xhdpi/ch_748_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_749_logo.png b/tests/common/res/drawable-xhdpi/ch_749_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_749_logo.png
rename to tests/common/res/drawable-xhdpi/ch_749_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_74_logo.png b/tests/common/res/drawable-xhdpi/ch_74_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_74_logo.png
rename to tests/common/res/drawable-xhdpi/ch_74_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_750_logo.png b/tests/common/res/drawable-xhdpi/ch_750_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_750_logo.png
rename to tests/common/res/drawable-xhdpi/ch_750_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_751_logo.png b/tests/common/res/drawable-xhdpi/ch_751_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_751_logo.png
rename to tests/common/res/drawable-xhdpi/ch_751_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_752_logo.png b/tests/common/res/drawable-xhdpi/ch_752_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_752_logo.png
rename to tests/common/res/drawable-xhdpi/ch_752_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_753_logo.png b/tests/common/res/drawable-xhdpi/ch_753_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_753_logo.png
rename to tests/common/res/drawable-xhdpi/ch_753_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_754_logo.png b/tests/common/res/drawable-xhdpi/ch_754_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_754_logo.png
rename to tests/common/res/drawable-xhdpi/ch_754_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_755_logo.png b/tests/common/res/drawable-xhdpi/ch_755_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_755_logo.png
rename to tests/common/res/drawable-xhdpi/ch_755_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_756_logo.png b/tests/common/res/drawable-xhdpi/ch_756_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_756_logo.png
rename to tests/common/res/drawable-xhdpi/ch_756_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_757_logo.png b/tests/common/res/drawable-xhdpi/ch_757_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_757_logo.png
rename to tests/common/res/drawable-xhdpi/ch_757_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_758_logo.png b/tests/common/res/drawable-xhdpi/ch_758_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_758_logo.png
rename to tests/common/res/drawable-xhdpi/ch_758_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_759_logo.png b/tests/common/res/drawable-xhdpi/ch_759_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_759_logo.png
rename to tests/common/res/drawable-xhdpi/ch_759_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_75_logo.png b/tests/common/res/drawable-xhdpi/ch_75_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_75_logo.png
rename to tests/common/res/drawable-xhdpi/ch_75_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_760_logo.png b/tests/common/res/drawable-xhdpi/ch_760_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_760_logo.png
rename to tests/common/res/drawable-xhdpi/ch_760_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_761_logo.png b/tests/common/res/drawable-xhdpi/ch_761_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_761_logo.png
rename to tests/common/res/drawable-xhdpi/ch_761_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_762_logo.png b/tests/common/res/drawable-xhdpi/ch_762_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_762_logo.png
rename to tests/common/res/drawable-xhdpi/ch_762_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_763_logo.png b/tests/common/res/drawable-xhdpi/ch_763_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_763_logo.png
rename to tests/common/res/drawable-xhdpi/ch_763_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_764_logo.png b/tests/common/res/drawable-xhdpi/ch_764_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_764_logo.png
rename to tests/common/res/drawable-xhdpi/ch_764_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_765_logo.png b/tests/common/res/drawable-xhdpi/ch_765_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_765_logo.png
rename to tests/common/res/drawable-xhdpi/ch_765_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_766_logo.png b/tests/common/res/drawable-xhdpi/ch_766_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_766_logo.png
rename to tests/common/res/drawable-xhdpi/ch_766_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_767_logo.png b/tests/common/res/drawable-xhdpi/ch_767_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_767_logo.png
rename to tests/common/res/drawable-xhdpi/ch_767_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_768_logo.png b/tests/common/res/drawable-xhdpi/ch_768_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_768_logo.png
rename to tests/common/res/drawable-xhdpi/ch_768_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_769_logo.png b/tests/common/res/drawable-xhdpi/ch_769_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_769_logo.png
rename to tests/common/res/drawable-xhdpi/ch_769_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_76_logo.png b/tests/common/res/drawable-xhdpi/ch_76_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_76_logo.png
rename to tests/common/res/drawable-xhdpi/ch_76_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_770_logo.png b/tests/common/res/drawable-xhdpi/ch_770_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_770_logo.png
rename to tests/common/res/drawable-xhdpi/ch_770_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_771_logo.png b/tests/common/res/drawable-xhdpi/ch_771_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_771_logo.png
rename to tests/common/res/drawable-xhdpi/ch_771_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_772_logo.png b/tests/common/res/drawable-xhdpi/ch_772_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_772_logo.png
rename to tests/common/res/drawable-xhdpi/ch_772_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_773_logo.png b/tests/common/res/drawable-xhdpi/ch_773_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_773_logo.png
rename to tests/common/res/drawable-xhdpi/ch_773_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_774_logo.png b/tests/common/res/drawable-xhdpi/ch_774_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_774_logo.png
rename to tests/common/res/drawable-xhdpi/ch_774_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_775_logo.png b/tests/common/res/drawable-xhdpi/ch_775_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_775_logo.png
rename to tests/common/res/drawable-xhdpi/ch_775_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_776_logo.png b/tests/common/res/drawable-xhdpi/ch_776_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_776_logo.png
rename to tests/common/res/drawable-xhdpi/ch_776_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_777_logo.png b/tests/common/res/drawable-xhdpi/ch_777_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_777_logo.png
rename to tests/common/res/drawable-xhdpi/ch_777_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_778_logo.png b/tests/common/res/drawable-xhdpi/ch_778_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_778_logo.png
rename to tests/common/res/drawable-xhdpi/ch_778_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_779_logo.png b/tests/common/res/drawable-xhdpi/ch_779_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_779_logo.png
rename to tests/common/res/drawable-xhdpi/ch_779_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_77_logo.png b/tests/common/res/drawable-xhdpi/ch_77_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_77_logo.png
rename to tests/common/res/drawable-xhdpi/ch_77_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_780_logo.png b/tests/common/res/drawable-xhdpi/ch_780_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_780_logo.png
rename to tests/common/res/drawable-xhdpi/ch_780_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_781_logo.png b/tests/common/res/drawable-xhdpi/ch_781_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_781_logo.png
rename to tests/common/res/drawable-xhdpi/ch_781_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_782_logo.png b/tests/common/res/drawable-xhdpi/ch_782_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_782_logo.png
rename to tests/common/res/drawable-xhdpi/ch_782_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_783_logo.png b/tests/common/res/drawable-xhdpi/ch_783_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_783_logo.png
rename to tests/common/res/drawable-xhdpi/ch_783_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_784_logo.png b/tests/common/res/drawable-xhdpi/ch_784_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_784_logo.png
rename to tests/common/res/drawable-xhdpi/ch_784_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_785_logo.png b/tests/common/res/drawable-xhdpi/ch_785_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_785_logo.png
rename to tests/common/res/drawable-xhdpi/ch_785_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_786_logo.png b/tests/common/res/drawable-xhdpi/ch_786_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_786_logo.png
rename to tests/common/res/drawable-xhdpi/ch_786_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_787_logo.png b/tests/common/res/drawable-xhdpi/ch_787_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_787_logo.png
rename to tests/common/res/drawable-xhdpi/ch_787_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_788_logo.png b/tests/common/res/drawable-xhdpi/ch_788_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_788_logo.png
rename to tests/common/res/drawable-xhdpi/ch_788_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_789_logo.png b/tests/common/res/drawable-xhdpi/ch_789_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_789_logo.png
rename to tests/common/res/drawable-xhdpi/ch_789_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_78_logo.png b/tests/common/res/drawable-xhdpi/ch_78_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_78_logo.png
rename to tests/common/res/drawable-xhdpi/ch_78_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_790_logo.png b/tests/common/res/drawable-xhdpi/ch_790_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_790_logo.png
rename to tests/common/res/drawable-xhdpi/ch_790_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_791_logo.png b/tests/common/res/drawable-xhdpi/ch_791_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_791_logo.png
rename to tests/common/res/drawable-xhdpi/ch_791_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_792_logo.png b/tests/common/res/drawable-xhdpi/ch_792_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_792_logo.png
rename to tests/common/res/drawable-xhdpi/ch_792_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_793_logo.png b/tests/common/res/drawable-xhdpi/ch_793_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_793_logo.png
rename to tests/common/res/drawable-xhdpi/ch_793_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_794_logo.png b/tests/common/res/drawable-xhdpi/ch_794_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_794_logo.png
rename to tests/common/res/drawable-xhdpi/ch_794_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_795_logo.png b/tests/common/res/drawable-xhdpi/ch_795_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_795_logo.png
rename to tests/common/res/drawable-xhdpi/ch_795_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_796_logo.png b/tests/common/res/drawable-xhdpi/ch_796_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_796_logo.png
rename to tests/common/res/drawable-xhdpi/ch_796_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_797_logo.png b/tests/common/res/drawable-xhdpi/ch_797_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_797_logo.png
rename to tests/common/res/drawable-xhdpi/ch_797_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_798_logo.png b/tests/common/res/drawable-xhdpi/ch_798_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_798_logo.png
rename to tests/common/res/drawable-xhdpi/ch_798_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_799_logo.png b/tests/common/res/drawable-xhdpi/ch_799_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_799_logo.png
rename to tests/common/res/drawable-xhdpi/ch_799_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_79_logo.png b/tests/common/res/drawable-xhdpi/ch_79_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_79_logo.png
rename to tests/common/res/drawable-xhdpi/ch_79_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_7_logo.png b/tests/common/res/drawable-xhdpi/ch_7_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_7_logo.png
rename to tests/common/res/drawable-xhdpi/ch_7_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_800_logo.png b/tests/common/res/drawable-xhdpi/ch_800_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_800_logo.png
rename to tests/common/res/drawable-xhdpi/ch_800_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_801_logo.png b/tests/common/res/drawable-xhdpi/ch_801_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_801_logo.png
rename to tests/common/res/drawable-xhdpi/ch_801_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_802_logo.png b/tests/common/res/drawable-xhdpi/ch_802_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_802_logo.png
rename to tests/common/res/drawable-xhdpi/ch_802_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_803_logo.png b/tests/common/res/drawable-xhdpi/ch_803_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_803_logo.png
rename to tests/common/res/drawable-xhdpi/ch_803_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_804_logo.png b/tests/common/res/drawable-xhdpi/ch_804_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_804_logo.png
rename to tests/common/res/drawable-xhdpi/ch_804_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_805_logo.png b/tests/common/res/drawable-xhdpi/ch_805_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_805_logo.png
rename to tests/common/res/drawable-xhdpi/ch_805_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_806_logo.png b/tests/common/res/drawable-xhdpi/ch_806_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_806_logo.png
rename to tests/common/res/drawable-xhdpi/ch_806_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_807_logo.png b/tests/common/res/drawable-xhdpi/ch_807_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_807_logo.png
rename to tests/common/res/drawable-xhdpi/ch_807_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_808_logo.png b/tests/common/res/drawable-xhdpi/ch_808_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_808_logo.png
rename to tests/common/res/drawable-xhdpi/ch_808_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_809_logo.png b/tests/common/res/drawable-xhdpi/ch_809_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_809_logo.png
rename to tests/common/res/drawable-xhdpi/ch_809_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_80_logo.png b/tests/common/res/drawable-xhdpi/ch_80_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_80_logo.png
rename to tests/common/res/drawable-xhdpi/ch_80_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_810_logo.png b/tests/common/res/drawable-xhdpi/ch_810_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_810_logo.png
rename to tests/common/res/drawable-xhdpi/ch_810_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_811_logo.png b/tests/common/res/drawable-xhdpi/ch_811_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_811_logo.png
rename to tests/common/res/drawable-xhdpi/ch_811_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_812_logo.png b/tests/common/res/drawable-xhdpi/ch_812_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_812_logo.png
rename to tests/common/res/drawable-xhdpi/ch_812_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_813_logo.png b/tests/common/res/drawable-xhdpi/ch_813_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_813_logo.png
rename to tests/common/res/drawable-xhdpi/ch_813_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_814_logo.png b/tests/common/res/drawable-xhdpi/ch_814_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_814_logo.png
rename to tests/common/res/drawable-xhdpi/ch_814_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_815_logo.png b/tests/common/res/drawable-xhdpi/ch_815_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_815_logo.png
rename to tests/common/res/drawable-xhdpi/ch_815_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_816_logo.png b/tests/common/res/drawable-xhdpi/ch_816_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_816_logo.png
rename to tests/common/res/drawable-xhdpi/ch_816_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_817_logo.png b/tests/common/res/drawable-xhdpi/ch_817_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_817_logo.png
rename to tests/common/res/drawable-xhdpi/ch_817_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_818_logo.png b/tests/common/res/drawable-xhdpi/ch_818_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_818_logo.png
rename to tests/common/res/drawable-xhdpi/ch_818_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_819_logo.png b/tests/common/res/drawable-xhdpi/ch_819_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_819_logo.png
rename to tests/common/res/drawable-xhdpi/ch_819_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_81_logo.png b/tests/common/res/drawable-xhdpi/ch_81_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_81_logo.png
rename to tests/common/res/drawable-xhdpi/ch_81_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_820_logo.png b/tests/common/res/drawable-xhdpi/ch_820_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_820_logo.png
rename to tests/common/res/drawable-xhdpi/ch_820_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_821_logo.png b/tests/common/res/drawable-xhdpi/ch_821_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_821_logo.png
rename to tests/common/res/drawable-xhdpi/ch_821_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_822_logo.png b/tests/common/res/drawable-xhdpi/ch_822_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_822_logo.png
rename to tests/common/res/drawable-xhdpi/ch_822_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_823_logo.png b/tests/common/res/drawable-xhdpi/ch_823_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_823_logo.png
rename to tests/common/res/drawable-xhdpi/ch_823_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_824_logo.png b/tests/common/res/drawable-xhdpi/ch_824_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_824_logo.png
rename to tests/common/res/drawable-xhdpi/ch_824_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_825_logo.png b/tests/common/res/drawable-xhdpi/ch_825_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_825_logo.png
rename to tests/common/res/drawable-xhdpi/ch_825_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_826_logo.png b/tests/common/res/drawable-xhdpi/ch_826_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_826_logo.png
rename to tests/common/res/drawable-xhdpi/ch_826_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_827_logo.png b/tests/common/res/drawable-xhdpi/ch_827_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_827_logo.png
rename to tests/common/res/drawable-xhdpi/ch_827_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_828_logo.png b/tests/common/res/drawable-xhdpi/ch_828_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_828_logo.png
rename to tests/common/res/drawable-xhdpi/ch_828_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_829_logo.png b/tests/common/res/drawable-xhdpi/ch_829_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_829_logo.png
rename to tests/common/res/drawable-xhdpi/ch_829_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_82_logo.png b/tests/common/res/drawable-xhdpi/ch_82_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_82_logo.png
rename to tests/common/res/drawable-xhdpi/ch_82_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_830_logo.png b/tests/common/res/drawable-xhdpi/ch_830_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_830_logo.png
rename to tests/common/res/drawable-xhdpi/ch_830_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_831_logo.png b/tests/common/res/drawable-xhdpi/ch_831_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_831_logo.png
rename to tests/common/res/drawable-xhdpi/ch_831_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_832_logo.png b/tests/common/res/drawable-xhdpi/ch_832_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_832_logo.png
rename to tests/common/res/drawable-xhdpi/ch_832_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_833_logo.png b/tests/common/res/drawable-xhdpi/ch_833_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_833_logo.png
rename to tests/common/res/drawable-xhdpi/ch_833_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_834_logo.png b/tests/common/res/drawable-xhdpi/ch_834_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_834_logo.png
rename to tests/common/res/drawable-xhdpi/ch_834_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_835_logo.png b/tests/common/res/drawable-xhdpi/ch_835_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_835_logo.png
rename to tests/common/res/drawable-xhdpi/ch_835_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_836_logo.png b/tests/common/res/drawable-xhdpi/ch_836_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_836_logo.png
rename to tests/common/res/drawable-xhdpi/ch_836_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_837_logo.png b/tests/common/res/drawable-xhdpi/ch_837_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_837_logo.png
rename to tests/common/res/drawable-xhdpi/ch_837_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_838_logo.png b/tests/common/res/drawable-xhdpi/ch_838_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_838_logo.png
rename to tests/common/res/drawable-xhdpi/ch_838_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_839_logo.png b/tests/common/res/drawable-xhdpi/ch_839_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_839_logo.png
rename to tests/common/res/drawable-xhdpi/ch_839_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_83_logo.png b/tests/common/res/drawable-xhdpi/ch_83_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_83_logo.png
rename to tests/common/res/drawable-xhdpi/ch_83_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_840_logo.png b/tests/common/res/drawable-xhdpi/ch_840_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_840_logo.png
rename to tests/common/res/drawable-xhdpi/ch_840_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_841_logo.png b/tests/common/res/drawable-xhdpi/ch_841_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_841_logo.png
rename to tests/common/res/drawable-xhdpi/ch_841_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_842_logo.png b/tests/common/res/drawable-xhdpi/ch_842_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_842_logo.png
rename to tests/common/res/drawable-xhdpi/ch_842_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_843_logo.png b/tests/common/res/drawable-xhdpi/ch_843_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_843_logo.png
rename to tests/common/res/drawable-xhdpi/ch_843_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_844_logo.png b/tests/common/res/drawable-xhdpi/ch_844_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_844_logo.png
rename to tests/common/res/drawable-xhdpi/ch_844_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_845_logo.png b/tests/common/res/drawable-xhdpi/ch_845_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_845_logo.png
rename to tests/common/res/drawable-xhdpi/ch_845_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_846_logo.png b/tests/common/res/drawable-xhdpi/ch_846_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_846_logo.png
rename to tests/common/res/drawable-xhdpi/ch_846_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_847_logo.png b/tests/common/res/drawable-xhdpi/ch_847_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_847_logo.png
rename to tests/common/res/drawable-xhdpi/ch_847_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_848_logo.png b/tests/common/res/drawable-xhdpi/ch_848_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_848_logo.png
rename to tests/common/res/drawable-xhdpi/ch_848_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_849_logo.png b/tests/common/res/drawable-xhdpi/ch_849_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_849_logo.png
rename to tests/common/res/drawable-xhdpi/ch_849_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_84_logo.png b/tests/common/res/drawable-xhdpi/ch_84_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_84_logo.png
rename to tests/common/res/drawable-xhdpi/ch_84_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_850_logo.png b/tests/common/res/drawable-xhdpi/ch_850_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_850_logo.png
rename to tests/common/res/drawable-xhdpi/ch_850_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_851_logo.png b/tests/common/res/drawable-xhdpi/ch_851_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_851_logo.png
rename to tests/common/res/drawable-xhdpi/ch_851_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_852_logo.png b/tests/common/res/drawable-xhdpi/ch_852_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_852_logo.png
rename to tests/common/res/drawable-xhdpi/ch_852_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_853_logo.png b/tests/common/res/drawable-xhdpi/ch_853_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_853_logo.png
rename to tests/common/res/drawable-xhdpi/ch_853_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_854_logo.png b/tests/common/res/drawable-xhdpi/ch_854_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_854_logo.png
rename to tests/common/res/drawable-xhdpi/ch_854_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_855_logo.png b/tests/common/res/drawable-xhdpi/ch_855_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_855_logo.png
rename to tests/common/res/drawable-xhdpi/ch_855_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_856_logo.png b/tests/common/res/drawable-xhdpi/ch_856_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_856_logo.png
rename to tests/common/res/drawable-xhdpi/ch_856_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_857_logo.png b/tests/common/res/drawable-xhdpi/ch_857_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_857_logo.png
rename to tests/common/res/drawable-xhdpi/ch_857_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_858_logo.png b/tests/common/res/drawable-xhdpi/ch_858_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_858_logo.png
rename to tests/common/res/drawable-xhdpi/ch_858_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_859_logo.png b/tests/common/res/drawable-xhdpi/ch_859_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_859_logo.png
rename to tests/common/res/drawable-xhdpi/ch_859_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_85_logo.png b/tests/common/res/drawable-xhdpi/ch_85_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_85_logo.png
rename to tests/common/res/drawable-xhdpi/ch_85_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_860_logo.png b/tests/common/res/drawable-xhdpi/ch_860_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_860_logo.png
rename to tests/common/res/drawable-xhdpi/ch_860_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_861_logo.png b/tests/common/res/drawable-xhdpi/ch_861_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_861_logo.png
rename to tests/common/res/drawable-xhdpi/ch_861_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_862_logo.png b/tests/common/res/drawable-xhdpi/ch_862_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_862_logo.png
rename to tests/common/res/drawable-xhdpi/ch_862_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_863_logo.png b/tests/common/res/drawable-xhdpi/ch_863_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_863_logo.png
rename to tests/common/res/drawable-xhdpi/ch_863_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_864_logo.png b/tests/common/res/drawable-xhdpi/ch_864_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_864_logo.png
rename to tests/common/res/drawable-xhdpi/ch_864_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_865_logo.png b/tests/common/res/drawable-xhdpi/ch_865_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_865_logo.png
rename to tests/common/res/drawable-xhdpi/ch_865_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_866_logo.png b/tests/common/res/drawable-xhdpi/ch_866_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_866_logo.png
rename to tests/common/res/drawable-xhdpi/ch_866_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_867_logo.png b/tests/common/res/drawable-xhdpi/ch_867_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_867_logo.png
rename to tests/common/res/drawable-xhdpi/ch_867_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_868_logo.png b/tests/common/res/drawable-xhdpi/ch_868_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_868_logo.png
rename to tests/common/res/drawable-xhdpi/ch_868_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_869_logo.png b/tests/common/res/drawable-xhdpi/ch_869_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_869_logo.png
rename to tests/common/res/drawable-xhdpi/ch_869_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_86_logo.png b/tests/common/res/drawable-xhdpi/ch_86_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_86_logo.png
rename to tests/common/res/drawable-xhdpi/ch_86_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_870_logo.png b/tests/common/res/drawable-xhdpi/ch_870_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_870_logo.png
rename to tests/common/res/drawable-xhdpi/ch_870_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_871_logo.png b/tests/common/res/drawable-xhdpi/ch_871_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_871_logo.png
rename to tests/common/res/drawable-xhdpi/ch_871_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_872_logo.png b/tests/common/res/drawable-xhdpi/ch_872_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_872_logo.png
rename to tests/common/res/drawable-xhdpi/ch_872_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_873_logo.png b/tests/common/res/drawable-xhdpi/ch_873_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_873_logo.png
rename to tests/common/res/drawable-xhdpi/ch_873_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_874_logo.png b/tests/common/res/drawable-xhdpi/ch_874_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_874_logo.png
rename to tests/common/res/drawable-xhdpi/ch_874_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_875_logo.png b/tests/common/res/drawable-xhdpi/ch_875_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_875_logo.png
rename to tests/common/res/drawable-xhdpi/ch_875_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_876_logo.png b/tests/common/res/drawable-xhdpi/ch_876_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_876_logo.png
rename to tests/common/res/drawable-xhdpi/ch_876_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_877_logo.png b/tests/common/res/drawable-xhdpi/ch_877_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_877_logo.png
rename to tests/common/res/drawable-xhdpi/ch_877_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_878_logo.png b/tests/common/res/drawable-xhdpi/ch_878_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_878_logo.png
rename to tests/common/res/drawable-xhdpi/ch_878_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_879_logo.png b/tests/common/res/drawable-xhdpi/ch_879_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_879_logo.png
rename to tests/common/res/drawable-xhdpi/ch_879_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_87_logo.png b/tests/common/res/drawable-xhdpi/ch_87_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_87_logo.png
rename to tests/common/res/drawable-xhdpi/ch_87_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_880_logo.png b/tests/common/res/drawable-xhdpi/ch_880_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_880_logo.png
rename to tests/common/res/drawable-xhdpi/ch_880_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_881_logo.png b/tests/common/res/drawable-xhdpi/ch_881_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_881_logo.png
rename to tests/common/res/drawable-xhdpi/ch_881_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_882_logo.png b/tests/common/res/drawable-xhdpi/ch_882_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_882_logo.png
rename to tests/common/res/drawable-xhdpi/ch_882_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_883_logo.png b/tests/common/res/drawable-xhdpi/ch_883_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_883_logo.png
rename to tests/common/res/drawable-xhdpi/ch_883_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_884_logo.png b/tests/common/res/drawable-xhdpi/ch_884_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_884_logo.png
rename to tests/common/res/drawable-xhdpi/ch_884_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_885_logo.png b/tests/common/res/drawable-xhdpi/ch_885_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_885_logo.png
rename to tests/common/res/drawable-xhdpi/ch_885_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_886_logo.png b/tests/common/res/drawable-xhdpi/ch_886_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_886_logo.png
rename to tests/common/res/drawable-xhdpi/ch_886_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_887_logo.png b/tests/common/res/drawable-xhdpi/ch_887_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_887_logo.png
rename to tests/common/res/drawable-xhdpi/ch_887_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_888_logo.png b/tests/common/res/drawable-xhdpi/ch_888_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_888_logo.png
rename to tests/common/res/drawable-xhdpi/ch_888_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_889_logo.png b/tests/common/res/drawable-xhdpi/ch_889_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_889_logo.png
rename to tests/common/res/drawable-xhdpi/ch_889_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_88_logo.png b/tests/common/res/drawable-xhdpi/ch_88_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_88_logo.png
rename to tests/common/res/drawable-xhdpi/ch_88_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_890_logo.png b/tests/common/res/drawable-xhdpi/ch_890_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_890_logo.png
rename to tests/common/res/drawable-xhdpi/ch_890_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_891_logo.png b/tests/common/res/drawable-xhdpi/ch_891_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_891_logo.png
rename to tests/common/res/drawable-xhdpi/ch_891_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_892_logo.png b/tests/common/res/drawable-xhdpi/ch_892_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_892_logo.png
rename to tests/common/res/drawable-xhdpi/ch_892_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_893_logo.png b/tests/common/res/drawable-xhdpi/ch_893_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_893_logo.png
rename to tests/common/res/drawable-xhdpi/ch_893_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_894_logo.png b/tests/common/res/drawable-xhdpi/ch_894_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_894_logo.png
rename to tests/common/res/drawable-xhdpi/ch_894_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_895_logo.png b/tests/common/res/drawable-xhdpi/ch_895_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_895_logo.png
rename to tests/common/res/drawable-xhdpi/ch_895_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_896_logo.png b/tests/common/res/drawable-xhdpi/ch_896_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_896_logo.png
rename to tests/common/res/drawable-xhdpi/ch_896_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_897_logo.png b/tests/common/res/drawable-xhdpi/ch_897_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_897_logo.png
rename to tests/common/res/drawable-xhdpi/ch_897_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_898_logo.png b/tests/common/res/drawable-xhdpi/ch_898_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_898_logo.png
rename to tests/common/res/drawable-xhdpi/ch_898_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_899_logo.png b/tests/common/res/drawable-xhdpi/ch_899_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_899_logo.png
rename to tests/common/res/drawable-xhdpi/ch_899_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_89_logo.png b/tests/common/res/drawable-xhdpi/ch_89_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_89_logo.png
rename to tests/common/res/drawable-xhdpi/ch_89_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_8_logo.png b/tests/common/res/drawable-xhdpi/ch_8_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_8_logo.png
rename to tests/common/res/drawable-xhdpi/ch_8_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_900_logo.png b/tests/common/res/drawable-xhdpi/ch_900_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_900_logo.png
rename to tests/common/res/drawable-xhdpi/ch_900_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_901_logo.png b/tests/common/res/drawable-xhdpi/ch_901_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_901_logo.png
rename to tests/common/res/drawable-xhdpi/ch_901_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_902_logo.png b/tests/common/res/drawable-xhdpi/ch_902_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_902_logo.png
rename to tests/common/res/drawable-xhdpi/ch_902_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_903_logo.png b/tests/common/res/drawable-xhdpi/ch_903_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_903_logo.png
rename to tests/common/res/drawable-xhdpi/ch_903_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_904_logo.png b/tests/common/res/drawable-xhdpi/ch_904_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_904_logo.png
rename to tests/common/res/drawable-xhdpi/ch_904_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_905_logo.png b/tests/common/res/drawable-xhdpi/ch_905_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_905_logo.png
rename to tests/common/res/drawable-xhdpi/ch_905_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_906_logo.png b/tests/common/res/drawable-xhdpi/ch_906_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_906_logo.png
rename to tests/common/res/drawable-xhdpi/ch_906_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_907_logo.png b/tests/common/res/drawable-xhdpi/ch_907_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_907_logo.png
rename to tests/common/res/drawable-xhdpi/ch_907_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_908_logo.png b/tests/common/res/drawable-xhdpi/ch_908_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_908_logo.png
rename to tests/common/res/drawable-xhdpi/ch_908_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_909_logo.png b/tests/common/res/drawable-xhdpi/ch_909_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_909_logo.png
rename to tests/common/res/drawable-xhdpi/ch_909_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_90_logo.png b/tests/common/res/drawable-xhdpi/ch_90_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_90_logo.png
rename to tests/common/res/drawable-xhdpi/ch_90_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_910_logo.png b/tests/common/res/drawable-xhdpi/ch_910_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_910_logo.png
rename to tests/common/res/drawable-xhdpi/ch_910_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_911_logo.png b/tests/common/res/drawable-xhdpi/ch_911_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_911_logo.png
rename to tests/common/res/drawable-xhdpi/ch_911_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_912_logo.png b/tests/common/res/drawable-xhdpi/ch_912_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_912_logo.png
rename to tests/common/res/drawable-xhdpi/ch_912_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_913_logo.png b/tests/common/res/drawable-xhdpi/ch_913_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_913_logo.png
rename to tests/common/res/drawable-xhdpi/ch_913_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_914_logo.png b/tests/common/res/drawable-xhdpi/ch_914_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_914_logo.png
rename to tests/common/res/drawable-xhdpi/ch_914_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_915_logo.png b/tests/common/res/drawable-xhdpi/ch_915_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_915_logo.png
rename to tests/common/res/drawable-xhdpi/ch_915_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_916_logo.png b/tests/common/res/drawable-xhdpi/ch_916_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_916_logo.png
rename to tests/common/res/drawable-xhdpi/ch_916_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_917_logo.png b/tests/common/res/drawable-xhdpi/ch_917_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_917_logo.png
rename to tests/common/res/drawable-xhdpi/ch_917_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_918_logo.png b/tests/common/res/drawable-xhdpi/ch_918_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_918_logo.png
rename to tests/common/res/drawable-xhdpi/ch_918_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_919_logo.png b/tests/common/res/drawable-xhdpi/ch_919_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_919_logo.png
rename to tests/common/res/drawable-xhdpi/ch_919_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_91_logo.png b/tests/common/res/drawable-xhdpi/ch_91_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_91_logo.png
rename to tests/common/res/drawable-xhdpi/ch_91_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_920_logo.png b/tests/common/res/drawable-xhdpi/ch_920_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_920_logo.png
rename to tests/common/res/drawable-xhdpi/ch_920_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_921_logo.png b/tests/common/res/drawable-xhdpi/ch_921_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_921_logo.png
rename to tests/common/res/drawable-xhdpi/ch_921_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_922_logo.png b/tests/common/res/drawable-xhdpi/ch_922_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_922_logo.png
rename to tests/common/res/drawable-xhdpi/ch_922_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_923_logo.png b/tests/common/res/drawable-xhdpi/ch_923_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_923_logo.png
rename to tests/common/res/drawable-xhdpi/ch_923_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_924_logo.png b/tests/common/res/drawable-xhdpi/ch_924_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_924_logo.png
rename to tests/common/res/drawable-xhdpi/ch_924_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_925_logo.png b/tests/common/res/drawable-xhdpi/ch_925_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_925_logo.png
rename to tests/common/res/drawable-xhdpi/ch_925_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_926_logo.png b/tests/common/res/drawable-xhdpi/ch_926_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_926_logo.png
rename to tests/common/res/drawable-xhdpi/ch_926_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_927_logo.png b/tests/common/res/drawable-xhdpi/ch_927_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_927_logo.png
rename to tests/common/res/drawable-xhdpi/ch_927_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_928_logo.png b/tests/common/res/drawable-xhdpi/ch_928_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_928_logo.png
rename to tests/common/res/drawable-xhdpi/ch_928_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_929_logo.png b/tests/common/res/drawable-xhdpi/ch_929_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_929_logo.png
rename to tests/common/res/drawable-xhdpi/ch_929_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_92_logo.png b/tests/common/res/drawable-xhdpi/ch_92_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_92_logo.png
rename to tests/common/res/drawable-xhdpi/ch_92_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_930_logo.png b/tests/common/res/drawable-xhdpi/ch_930_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_930_logo.png
rename to tests/common/res/drawable-xhdpi/ch_930_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_931_logo.png b/tests/common/res/drawable-xhdpi/ch_931_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_931_logo.png
rename to tests/common/res/drawable-xhdpi/ch_931_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_932_logo.png b/tests/common/res/drawable-xhdpi/ch_932_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_932_logo.png
rename to tests/common/res/drawable-xhdpi/ch_932_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_933_logo.png b/tests/common/res/drawable-xhdpi/ch_933_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_933_logo.png
rename to tests/common/res/drawable-xhdpi/ch_933_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_934_logo.png b/tests/common/res/drawable-xhdpi/ch_934_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_934_logo.png
rename to tests/common/res/drawable-xhdpi/ch_934_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_935_logo.png b/tests/common/res/drawable-xhdpi/ch_935_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_935_logo.png
rename to tests/common/res/drawable-xhdpi/ch_935_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_936_logo.png b/tests/common/res/drawable-xhdpi/ch_936_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_936_logo.png
rename to tests/common/res/drawable-xhdpi/ch_936_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_937_logo.png b/tests/common/res/drawable-xhdpi/ch_937_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_937_logo.png
rename to tests/common/res/drawable-xhdpi/ch_937_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_938_logo.png b/tests/common/res/drawable-xhdpi/ch_938_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_938_logo.png
rename to tests/common/res/drawable-xhdpi/ch_938_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_939_logo.png b/tests/common/res/drawable-xhdpi/ch_939_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_939_logo.png
rename to tests/common/res/drawable-xhdpi/ch_939_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_93_logo.png b/tests/common/res/drawable-xhdpi/ch_93_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_93_logo.png
rename to tests/common/res/drawable-xhdpi/ch_93_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_940_logo.png b/tests/common/res/drawable-xhdpi/ch_940_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_940_logo.png
rename to tests/common/res/drawable-xhdpi/ch_940_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_941_logo.png b/tests/common/res/drawable-xhdpi/ch_941_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_941_logo.png
rename to tests/common/res/drawable-xhdpi/ch_941_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_942_logo.png b/tests/common/res/drawable-xhdpi/ch_942_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_942_logo.png
rename to tests/common/res/drawable-xhdpi/ch_942_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_943_logo.png b/tests/common/res/drawable-xhdpi/ch_943_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_943_logo.png
rename to tests/common/res/drawable-xhdpi/ch_943_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_944_logo.png b/tests/common/res/drawable-xhdpi/ch_944_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_944_logo.png
rename to tests/common/res/drawable-xhdpi/ch_944_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_945_logo.png b/tests/common/res/drawable-xhdpi/ch_945_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_945_logo.png
rename to tests/common/res/drawable-xhdpi/ch_945_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_946_logo.png b/tests/common/res/drawable-xhdpi/ch_946_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_946_logo.png
rename to tests/common/res/drawable-xhdpi/ch_946_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_947_logo.png b/tests/common/res/drawable-xhdpi/ch_947_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_947_logo.png
rename to tests/common/res/drawable-xhdpi/ch_947_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_948_logo.png b/tests/common/res/drawable-xhdpi/ch_948_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_948_logo.png
rename to tests/common/res/drawable-xhdpi/ch_948_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_949_logo.png b/tests/common/res/drawable-xhdpi/ch_949_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_949_logo.png
rename to tests/common/res/drawable-xhdpi/ch_949_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_94_logo.png b/tests/common/res/drawable-xhdpi/ch_94_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_94_logo.png
rename to tests/common/res/drawable-xhdpi/ch_94_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_950_logo.png b/tests/common/res/drawable-xhdpi/ch_950_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_950_logo.png
rename to tests/common/res/drawable-xhdpi/ch_950_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_951_logo.png b/tests/common/res/drawable-xhdpi/ch_951_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_951_logo.png
rename to tests/common/res/drawable-xhdpi/ch_951_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_952_logo.png b/tests/common/res/drawable-xhdpi/ch_952_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_952_logo.png
rename to tests/common/res/drawable-xhdpi/ch_952_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_953_logo.png b/tests/common/res/drawable-xhdpi/ch_953_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_953_logo.png
rename to tests/common/res/drawable-xhdpi/ch_953_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_954_logo.png b/tests/common/res/drawable-xhdpi/ch_954_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_954_logo.png
rename to tests/common/res/drawable-xhdpi/ch_954_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_955_logo.png b/tests/common/res/drawable-xhdpi/ch_955_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_955_logo.png
rename to tests/common/res/drawable-xhdpi/ch_955_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_956_logo.png b/tests/common/res/drawable-xhdpi/ch_956_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_956_logo.png
rename to tests/common/res/drawable-xhdpi/ch_956_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_957_logo.png b/tests/common/res/drawable-xhdpi/ch_957_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_957_logo.png
rename to tests/common/res/drawable-xhdpi/ch_957_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_958_logo.png b/tests/common/res/drawable-xhdpi/ch_958_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_958_logo.png
rename to tests/common/res/drawable-xhdpi/ch_958_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_959_logo.png b/tests/common/res/drawable-xhdpi/ch_959_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_959_logo.png
rename to tests/common/res/drawable-xhdpi/ch_959_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_95_logo.png b/tests/common/res/drawable-xhdpi/ch_95_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_95_logo.png
rename to tests/common/res/drawable-xhdpi/ch_95_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_960_logo.png b/tests/common/res/drawable-xhdpi/ch_960_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_960_logo.png
rename to tests/common/res/drawable-xhdpi/ch_960_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_961_logo.png b/tests/common/res/drawable-xhdpi/ch_961_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_961_logo.png
rename to tests/common/res/drawable-xhdpi/ch_961_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_962_logo.png b/tests/common/res/drawable-xhdpi/ch_962_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_962_logo.png
rename to tests/common/res/drawable-xhdpi/ch_962_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_963_logo.png b/tests/common/res/drawable-xhdpi/ch_963_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_963_logo.png
rename to tests/common/res/drawable-xhdpi/ch_963_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_964_logo.png b/tests/common/res/drawable-xhdpi/ch_964_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_964_logo.png
rename to tests/common/res/drawable-xhdpi/ch_964_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_965_logo.png b/tests/common/res/drawable-xhdpi/ch_965_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_965_logo.png
rename to tests/common/res/drawable-xhdpi/ch_965_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_966_logo.png b/tests/common/res/drawable-xhdpi/ch_966_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_966_logo.png
rename to tests/common/res/drawable-xhdpi/ch_966_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_967_logo.png b/tests/common/res/drawable-xhdpi/ch_967_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_967_logo.png
rename to tests/common/res/drawable-xhdpi/ch_967_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_968_logo.png b/tests/common/res/drawable-xhdpi/ch_968_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_968_logo.png
rename to tests/common/res/drawable-xhdpi/ch_968_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_969_logo.png b/tests/common/res/drawable-xhdpi/ch_969_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_969_logo.png
rename to tests/common/res/drawable-xhdpi/ch_969_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_96_logo.png b/tests/common/res/drawable-xhdpi/ch_96_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_96_logo.png
rename to tests/common/res/drawable-xhdpi/ch_96_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_970_logo.png b/tests/common/res/drawable-xhdpi/ch_970_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_970_logo.png
rename to tests/common/res/drawable-xhdpi/ch_970_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_971_logo.png b/tests/common/res/drawable-xhdpi/ch_971_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_971_logo.png
rename to tests/common/res/drawable-xhdpi/ch_971_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_972_logo.png b/tests/common/res/drawable-xhdpi/ch_972_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_972_logo.png
rename to tests/common/res/drawable-xhdpi/ch_972_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_973_logo.png b/tests/common/res/drawable-xhdpi/ch_973_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_973_logo.png
rename to tests/common/res/drawable-xhdpi/ch_973_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_974_logo.png b/tests/common/res/drawable-xhdpi/ch_974_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_974_logo.png
rename to tests/common/res/drawable-xhdpi/ch_974_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_975_logo.png b/tests/common/res/drawable-xhdpi/ch_975_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_975_logo.png
rename to tests/common/res/drawable-xhdpi/ch_975_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_976_logo.png b/tests/common/res/drawable-xhdpi/ch_976_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_976_logo.png
rename to tests/common/res/drawable-xhdpi/ch_976_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_977_logo.png b/tests/common/res/drawable-xhdpi/ch_977_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_977_logo.png
rename to tests/common/res/drawable-xhdpi/ch_977_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_978_logo.png b/tests/common/res/drawable-xhdpi/ch_978_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_978_logo.png
rename to tests/common/res/drawable-xhdpi/ch_978_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_979_logo.png b/tests/common/res/drawable-xhdpi/ch_979_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_979_logo.png
rename to tests/common/res/drawable-xhdpi/ch_979_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_97_logo.png b/tests/common/res/drawable-xhdpi/ch_97_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_97_logo.png
rename to tests/common/res/drawable-xhdpi/ch_97_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_980_logo.png b/tests/common/res/drawable-xhdpi/ch_980_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_980_logo.png
rename to tests/common/res/drawable-xhdpi/ch_980_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_981_logo.png b/tests/common/res/drawable-xhdpi/ch_981_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_981_logo.png
rename to tests/common/res/drawable-xhdpi/ch_981_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_982_logo.png b/tests/common/res/drawable-xhdpi/ch_982_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_982_logo.png
rename to tests/common/res/drawable-xhdpi/ch_982_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_983_logo.png b/tests/common/res/drawable-xhdpi/ch_983_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_983_logo.png
rename to tests/common/res/drawable-xhdpi/ch_983_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_984_logo.png b/tests/common/res/drawable-xhdpi/ch_984_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_984_logo.png
rename to tests/common/res/drawable-xhdpi/ch_984_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_985_logo.png b/tests/common/res/drawable-xhdpi/ch_985_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_985_logo.png
rename to tests/common/res/drawable-xhdpi/ch_985_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_986_logo.png b/tests/common/res/drawable-xhdpi/ch_986_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_986_logo.png
rename to tests/common/res/drawable-xhdpi/ch_986_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_987_logo.png b/tests/common/res/drawable-xhdpi/ch_987_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_987_logo.png
rename to tests/common/res/drawable-xhdpi/ch_987_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_988_logo.png b/tests/common/res/drawable-xhdpi/ch_988_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_988_logo.png
rename to tests/common/res/drawable-xhdpi/ch_988_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_989_logo.png b/tests/common/res/drawable-xhdpi/ch_989_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_989_logo.png
rename to tests/common/res/drawable-xhdpi/ch_989_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_98_logo.png b/tests/common/res/drawable-xhdpi/ch_98_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_98_logo.png
rename to tests/common/res/drawable-xhdpi/ch_98_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_990_logo.png b/tests/common/res/drawable-xhdpi/ch_990_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_990_logo.png
rename to tests/common/res/drawable-xhdpi/ch_990_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_991_logo.png b/tests/common/res/drawable-xhdpi/ch_991_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_991_logo.png
rename to tests/common/res/drawable-xhdpi/ch_991_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_992_logo.png b/tests/common/res/drawable-xhdpi/ch_992_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_992_logo.png
rename to tests/common/res/drawable-xhdpi/ch_992_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_993_logo.png b/tests/common/res/drawable-xhdpi/ch_993_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_993_logo.png
rename to tests/common/res/drawable-xhdpi/ch_993_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_994_logo.png b/tests/common/res/drawable-xhdpi/ch_994_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_994_logo.png
rename to tests/common/res/drawable-xhdpi/ch_994_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_995_logo.png b/tests/common/res/drawable-xhdpi/ch_995_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_995_logo.png
rename to tests/common/res/drawable-xhdpi/ch_995_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_996_logo.png b/tests/common/res/drawable-xhdpi/ch_996_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_996_logo.png
rename to tests/common/res/drawable-xhdpi/ch_996_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_997_logo.png b/tests/common/res/drawable-xhdpi/ch_997_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_997_logo.png
rename to tests/common/res/drawable-xhdpi/ch_997_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_998_logo.png b/tests/common/res/drawable-xhdpi/ch_998_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_998_logo.png
rename to tests/common/res/drawable-xhdpi/ch_998_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_999_logo.png b/tests/common/res/drawable-xhdpi/ch_999_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_999_logo.png
rename to tests/common/res/drawable-xhdpi/ch_999_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_99_logo.png b/tests/common/res/drawable-xhdpi/ch_99_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_99_logo.png
rename to tests/common/res/drawable-xhdpi/ch_99_logo.png
Binary files differ
diff --git a/tests/input/res/drawable-xhdpi/ch_9_logo.png b/tests/common/res/drawable-xhdpi/ch_9_logo.png
similarity index 100%
rename from tests/input/res/drawable-xhdpi/ch_9_logo.png
rename to tests/common/res/drawable-xhdpi/ch_9_logo.png
Binary files differ
diff --git a/tests/common/src/com/android/tv/testing/ChannelInfo.java b/tests/common/src/com/android/tv/testing/ChannelInfo.java
index af1c989..946c0b5 100644
--- a/tests/common/src/com/android/tv/testing/ChannelInfo.java
+++ b/tests/common/src/com/android/tv/testing/ChannelInfo.java
@@ -16,9 +16,11 @@
 
 package com.android.tv.testing;
 
+import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
 import android.media.tv.TvContract;
+import android.net.Uri;
 import android.support.annotation.Nullable;
 import android.util.SparseArray;
 
@@ -38,11 +40,6 @@
         VIDEO_HEIGHT_TO_FORMAT_MAP.put(4320, TvContract.Channels.VIDEO_FORMAT_4320P);
     }
 
-    /**
-     * If this is specify for logo, it will be selected randomly including null.
-     */
-    public static final String GENERATE_LOGO = "GEN";
-
     public static final String[] PROJECTION = {
             TvContract.Channels.COLUMN_DISPLAY_NUMBER,
             TvContract.Channels.COLUMN_DISPLAY_NAME,
@@ -80,15 +77,20 @@
                 .setOriginalNetworkId(channelNumber);
         if (context != null) {
             // tests/input/tools/get_test_logos.sh only stores 1000 logos.
-            int logo_num = (channelNumber % 1000);
-            builder.setLogoUrl(
-                    "android.resource://com.android.tv.testinput/drawable/ch_" + logo_num
-                            + "_logo"
-            );
+            builder.setLogoUrl(getUriStringForChannelLogo(context, channelNumber));
         }
         return builder.build();
     }
 
+    public static String getUriStringForChannelLogo(Context context, int logoIndex) {
+        int index = (logoIndex % 1000) + 1;
+        return new Uri.Builder()
+                .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+                .authority(context.getPackageName())
+                .path("drawable")
+                .appendPath("ch_" + index + "_logo").build().toString();
+    }
+
     public static ChannelInfo fromCursor(Cursor c) {
         // TODO: Fill other fields.
         Builder builder = new Builder();
diff --git a/tests/common/src/com/android/tv/testing/Utils.java b/tests/common/src/com/android/tv/testing/Utils.java
index 66a1346..b2b4036 100644
--- a/tests/common/src/com/android/tv/testing/Utils.java
+++ b/tests/common/src/com/android/tv/testing/Utils.java
@@ -19,16 +19,15 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.content.res.Resources;
 import android.media.tv.TvInputInfo;
 import android.media.tv.TvInputManager;
 import android.net.Uri;
-import android.os.Looper;
 import android.util.Log;
 
 import com.android.tv.common.TvCommonUtils;
-import com.android.tv.util.MainThreadExecutor;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -37,8 +36,6 @@
 import java.util.Date;
 import java.util.Locale;
 import java.util.Random;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 
 /**
  * An utility class for testing.
@@ -101,27 +98,6 @@
         return new Random(DEFAULT_RANDOM_SEED);
     }
 
-    /**
-     * Executes a call on the main thread, blocking until it is completed.
-     *
-     * <p>Useful for doing things that are not thread-safe, such as looking at or modifying the view
-     * hierarchy.
-     *
-     * @param runnable The code to run on the main thread.
-     */
-    public static void runOnMainSync(Runnable runnable) {
-        if (Looper.myLooper() == Looper.getMainLooper()) {
-            runnable.run();
-        } else {
-            Future<?> temp = MainThreadExecutor.getInstance().submit(runnable);
-            try {
-                temp.get();
-            } catch (InterruptedException | ExecutionException e) {
-                throw new RuntimeException(e);
-            }
-        }
-    }
-
     private static long getSeed() {
         // Set random seed as the date to track failed test data easily.
         SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
@@ -131,4 +107,16 @@
     }
 
     private Utils() {}
+
+    /**
+     * Checks whether TvActivity is enabled or not.
+     */
+    public static boolean isTvActivityEnabled(Context context) {
+        PackageManager pm = context.getPackageManager();
+        ComponentName name = new ComponentName("com.android.tv",
+                "com.android.tv.TvActivity");
+        int enabled = pm.getComponentEnabledSetting(name);
+        return enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+    }
 }
diff --git a/tests/common/src/com/android/tv/testing/dvr/RecordingTestUtils.java b/tests/common/src/com/android/tv/testing/dvr/RecordingTestUtils.java
index b9def95..a9bfa97 100644
--- a/tests/common/src/com/android/tv/testing/dvr/RecordingTestUtils.java
+++ b/tests/common/src/com/android/tv/testing/dvr/RecordingTestUtils.java
@@ -16,7 +16,7 @@
 
 package com.android.tv.testing.dvr;
 
-import com.android.tv.dvr.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording;
 
 import junit.framework.Assert;
 
diff --git a/tests/common/src/com/android/tv/testing/uihelper/Constants.java b/tests/common/src/com/android/tv/testing/uihelper/Constants.java
index 8f607fb..8dd8e14 100644
--- a/tests/common/src/com/android/tv/testing/uihelper/Constants.java
+++ b/tests/common/src/com/android/tv/testing/uihelper/Constants.java
@@ -23,6 +23,7 @@
     public static final double EXTRA_TIMEOUT_PERCENT = .05;
     public static final int MIN_EXTRA_TIMEOUT = 10;
     public static final long MAX_SHOW_DELAY_MILLIS = 200;
+    public static final long MAX_FOCUSED_DELAY_MILLIS = 1000;
     public static final String TV_APP_PACKAGE = "com.android.tv";
     public static final BySelector TV_VIEW = By.res(TV_APP_PACKAGE, "main_tunable_tv_view");
     public static final BySelector CHANNEL_BANNER = By.res(TV_APP_PACKAGE, "channel_banner_view");
@@ -30,6 +31,8 @@
     public static final BySelector MENU = By.res(TV_APP_PACKAGE, "menu");
     public static final BySelector SIDE_PANEL = By.res(TV_APP_PACKAGE, "side_panel");
     public static final BySelector PROGRAM_GUIDE = By.res(TV_APP_PACKAGE, "program_guide");
+    public static final BySelector DVR_LIBRARY = By.res(TV_APP_PACKAGE, "dvr_frame");
+    public static final BySelector DVR_SCHEDULES = By.res(TV_APP_PACKAGE, "dvr_schedules");
     public static final BySelector FOCUSED_VIEW = By.focused(true);
 
     private Constants() {
diff --git a/tests/common/src/com/android/tv/testing/uihelper/LiveChannelsUiDeviceHelper.java b/tests/common/src/com/android/tv/testing/uihelper/LiveChannelsUiDeviceHelper.java
index 6757cf0..1dc0f02 100644
--- a/tests/common/src/com/android/tv/testing/uihelper/LiveChannelsUiDeviceHelper.java
+++ b/tests/common/src/com/android/tv/testing/uihelper/LiveChannelsUiDeviceHelper.java
@@ -1,6 +1,7 @@
 package com.android.tv.testing.uihelper;
 
 import static com.android.tv.testing.uihelper.UiDeviceAsserts.waitForCondition;
+import static junit.framework.TestCase.assertTrue;
 
 import android.content.Context;
 import android.content.Intent;
@@ -11,6 +12,8 @@
 import android.support.test.uiautomator.Until;
 import android.util.Log;
 
+import com.android.tv.testing.Utils;
+
 import junit.framework.Assert;
 
 /**
@@ -29,6 +32,7 @@
     }
 
     public void assertAppStarted() {
+        assertTrue("TvActivity should be enabled.", Utils.isTvActivityEnabled(mContext));
         Intent intent = mContext.getPackageManager()
                 .getLaunchIntentForPackage(Constants.TV_APP_PACKAGE);
         intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);    // Clear out any previous instances
@@ -48,4 +52,11 @@
             mUiDevice.pressBack();
         }
     }
+
+    public void assertAppStopped() {
+        while(mUiDevice.hasObject(By.pkg(Constants.TV_APP_PACKAGE).depth(0))) {
+            mUiDevice.pressBack();
+            mUiDevice.waitForIdle();
+        }
+    }
 }
\ No newline at end of file
diff --git a/tests/common/src/com/android/tv/testing/uihelper/MenuHelper.java b/tests/common/src/com/android/tv/testing/uihelper/MenuHelper.java
index ea5360a..80d5324 100644
--- a/tests/common/src/com/android/tv/testing/uihelper/MenuHelper.java
+++ b/tests/common/src/com/android/tv/testing/uihelper/MenuHelper.java
@@ -139,6 +139,11 @@
                 R.string.channels_item_program_guide);
     }
 
+    public UiObject2 assertPressDvrLibrary() {
+        return assertPressMenuItem(R.string.menu_title_channels,
+                R.string.channels_item_dvr);
+    }
+
     /**
      * Navigate to the menu item with the text {@code itemTextResId} in the row with text
      * {@code rowTitleResId}.
@@ -171,7 +176,11 @@
     public void showMenu() {
         if (!mUiDevice.hasObject(MENU)) {
             mUiDevice.pressMenu();
-            UiDeviceAsserts.assertWaitForCondition(mUiDevice, Until.hasObject(MENU));
+            if (!UiDeviceAsserts.waitForCondition(mUiDevice, Until.hasObject(MENU))) {
+                // Sometimes animations might block menu key, try again to make sure it's received.
+                mUiDevice.pressMenu();
+                UiDeviceAsserts.assertWaitForCondition(mUiDevice, Until.hasObject(MENU));
+            }
         }
     }
 }
diff --git a/tests/common/src/com/android/tv/testing/uihelper/SidePanelHelper.java b/tests/common/src/com/android/tv/testing/uihelper/SidePanelHelper.java
index 2d4f9b2..98a19a4 100644
--- a/tests/common/src/com/android/tv/testing/uihelper/SidePanelHelper.java
+++ b/tests/common/src/com/android/tv/testing/uihelper/SidePanelHelper.java
@@ -47,17 +47,23 @@
     }
 
     public UiObject2 assertNavigateToItem(int resId) {
-        String title = mTargetResources.getString(resId);
-        return assertNavigateToItem(title);
+        return assertNavigateToItem(resId, Direction.DOWN);
     }
 
+    public UiObject2 assertNavigateToItem(int resId, Direction direction) {
+        String title = mTargetResources.getString(resId);
+        return assertNavigateToItem(title, direction);
+    }
     public UiObject2 assertNavigateToItem(String title) {
+        return assertNavigateToItem(title, Direction.DOWN);
+    }
+
+    public UiObject2 assertNavigateToItem(String title, Direction direction) {
         BySelector sidePanelSelector = ByResource.id(mTargetResources, R.id.side_panel_list);
         UiObject2 sidePanelList = mUiDevice.findObject(sidePanelSelector);
         Assert.assertNotNull(sidePanelSelector + " not found", sidePanelList);
 
-        return UiDeviceAsserts
-                .assertNavigateTo(mUiDevice, sidePanelList, By.hasDescendant(By.text(title)),
-                        Direction.DOWN);
+        return UiDeviceAsserts.assertNavigateTo(mUiDevice, sidePanelList,
+                By.hasDescendant(By.text(title)), direction);
     }
 }
diff --git a/tests/common/src/com/android/tv/testing/uihelper/UiDeviceAsserts.java b/tests/common/src/com/android/tv/testing/uihelper/UiDeviceAsserts.java
index ea9b546..c096d7d 100644
--- a/tests/common/src/com/android/tv/testing/uihelper/UiDeviceAsserts.java
+++ b/tests/common/src/com/android/tv/testing/uihelper/UiDeviceAsserts.java
@@ -17,6 +17,7 @@
 
 import static com.android.tv.testing.uihelper.Constants.FOCUSED_VIEW;
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertTrue;
 
 import android.support.test.uiautomator.By;
@@ -38,6 +39,12 @@
         assertEquals("Has " + bySelector, expected, uiDevice.hasObject(bySelector));
     }
 
+    public static void assertWaitUntilFocused(UiDevice uiDevice, BySelector bySelector) {
+        UiObject2 uiObject = uiDevice.findObject(bySelector);
+        assertNotNull(uiObject);
+        assertTrue(uiObject.wait(Until.focused(true), Constants.MAX_FOCUSED_DELAY_MILLIS));
+    }
+
     /**
      * Assert that {@code searchCondition} becomes true within
      * {@value Constants#MAX_SHOW_DELAY_MILLIS} milliseconds.
diff --git a/tests/common/src/com/android/tv/testing/uihelper/UiDeviceUtils.java b/tests/common/src/com/android/tv/testing/uihelper/UiDeviceUtils.java
index 577559c..98eff90 100644
--- a/tests/common/src/com/android/tv/testing/uihelper/UiDeviceUtils.java
+++ b/tests/common/src/com/android/tv/testing/uihelper/UiDeviceUtils.java
@@ -15,8 +15,16 @@
  */
 package com.android.tv.testing.uihelper;
 
+import static junit.framework.Assert.assertTrue;
+
+import android.app.Instrumentation;
+import android.app.UiAutomation;
+import android.os.Build;
+import android.os.SystemClock;
+import android.support.test.uiautomator.Configurator;
 import android.support.test.uiautomator.Direction;
 import android.support.test.uiautomator.UiDevice;
+import android.view.InputDevice;
 import android.view.KeyEvent;
 
 /**
@@ -51,7 +59,7 @@
     }
 
     /**
-     * Parses the string and sends the corresponding individual key preses.
+     * Parses the string and sends the corresponding individual key presses.
      * <p>
      * <b>Note:</b> only handles 0-9, '.', and '-'.
      */
@@ -69,6 +77,59 @@
         }
     }
 
+    /**
+     * Sends the DPAD Center key presses with the {@code repeat} count.
+     * TODO: Remove instrumentation argument once migrated to JUnit4.
+     */
+    public static void pressDPadCenter(Instrumentation instrumentation, int repeat) {
+        pressKey(instrumentation, KeyEvent.KEYCODE_DPAD_CENTER, repeat);
+    }
+
+    private static void pressKey(Instrumentation instrumentation, int keyCode, int repeat) {
+        UiDevice.getInstance(instrumentation).waitForIdle();
+        for (int i = 0; i < repeat; ++i) {
+            assertPressKeyDown(instrumentation, keyCode, false);
+            if (i < repeat - 1) {
+                assertPressKeyUp(instrumentation, keyCode, false);
+            }
+        }
+        // Send last key event synchronously.
+        assertPressKeyUp(instrumentation, keyCode, true);
+    }
+
+    private static void assertPressKeyDown(Instrumentation instrumentation, int keyCode,
+            boolean sync) {
+        assertPressKey(instrumentation, KeyEvent.ACTION_DOWN, keyCode, sync);
+    }
+
+    private static void assertPressKeyUp(Instrumentation instrumentation, int keyCode,
+            boolean sync) {
+        assertPressKey(instrumentation, KeyEvent.ACTION_UP, keyCode, sync);
+    }
+
+    private static void assertPressKey(Instrumentation instrumentation, int action, int keyCode,
+            boolean sync) {
+        long eventTime = SystemClock.uptimeMillis();
+        KeyEvent event = new KeyEvent(eventTime, eventTime, action, keyCode, 0, 0, -1, 0, 0,
+                InputDevice.SOURCE_KEYBOARD);
+        assertTrue("Failed to inject key up event:" + event,
+                injectEvent(instrumentation, event, sync));
+    }
+
+    private static boolean injectEvent(Instrumentation instrumentation, KeyEvent event,
+            boolean sync) {
+        return getUiAutomation(instrumentation).injectInputEvent(event, sync);
+    }
+
+    private static UiAutomation getUiAutomation(Instrumentation instrumentation) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            int flags = Configurator.getInstance().getUiAutomationFlags();
+            return instrumentation.getUiAutomation(flags);
+        } else {
+            return instrumentation.getUiAutomation();
+        }
+    }
+
     private UiDeviceUtils() {
     }
 }
diff --git a/tests/func/Android.mk b/tests/func/Android.mk
index b0c5ad1..e89ba25 100644
--- a/tests/func/Android.mk
+++ b/tests/func/Android.mk
@@ -14,8 +14,6 @@
     tv-test-common \
     ub-uiautomator \
 
-LOCAL_JAVA_LIBRARIES := legacy-android-test
-
 LOCAL_INSTRUMENTATION_FOR := LiveTv
 
 LOCAL_SDK_VERSION := current
diff --git a/tests/func/OWNERS b/tests/func/OWNERS
new file mode 100644
index 0000000..4aa5fe5
--- /dev/null
+++ b/tests/func/OWNERS
@@ -0,0 +1,2 @@
+nchalko@google.com
+shubang@google.com
diff --git a/tests/func/src/com/android/tv/tests/ui/ChannelSourcesTest.java b/tests/func/src/com/android/tv/tests/ui/ChannelSourcesTest.java
index e4f612e..cfa5eda 100644
--- a/tests/func/src/com/android/tv/tests/ui/ChannelSourcesTest.java
+++ b/tests/func/src/com/android/tv/tests/ui/ChannelSourcesTest.java
@@ -23,6 +23,7 @@
 
 import com.android.tv.R;
 import com.android.tv.testing.uihelper.ByResource;
+import com.android.tv.testing.uihelper.UiDeviceUtils;
 
 /**
  * Tests for channel sources.
@@ -60,8 +61,7 @@
         assertWaitForCondition(mDevice, Until.hasObject(mBySettingsSidePanel));
 
         mSidePanelHelper.assertNavigateToItem(R.string.settings_channel_source_item_setup);
-        mDevice.pressDPadCenter();
-        mDevice.pressDPadCenter();
+        UiDeviceUtils.pressDPadCenter(getInstrumentation(), 2);
 
         assertWaitForCondition(mDevice,
                 Until.hasObject(ByResource.text(mTargetResources, R.string.setup_sources_text)));
diff --git a/tests/func/src/com/android/tv/tests/ui/LiveChannelsTestCase.java b/tests/func/src/com/android/tv/tests/ui/LiveChannelsTestCase.java
index 25c7909..e306e6c 100644
--- a/tests/func/src/com/android/tv/tests/ui/LiveChannelsTestCase.java
+++ b/tests/func/src/com/android/tv/tests/ui/LiveChannelsTestCase.java
@@ -73,6 +73,8 @@
                 .hasObject(Constants.PROGRAM_GUIDE)) {
             mDevice.pressBack();
         }
+        // To destroy the activity to make sure next test case's activity launch check works well.
+        mDevice.pressBack();
         super.tearDown();
     }
 
diff --git a/tests/func/src/com/android/tv/tests/ui/PlayControlsRowViewTest.java b/tests/func/src/com/android/tv/tests/ui/PlayControlsRowViewTest.java
index bbc7aa8..82c6a81 100644
--- a/tests/func/src/com/android/tv/tests/ui/PlayControlsRowViewTest.java
+++ b/tests/func/src/com/android/tv/tests/ui/PlayControlsRowViewTest.java
@@ -16,11 +16,11 @@
 
 package com.android.tv.tests.ui;
 
+import static com.android.tv.testing.uihelper.Constants.CHANNEL_BANNER;
 import static com.android.tv.testing.uihelper.Constants.FOCUSED_VIEW;
 import static com.android.tv.testing.uihelper.Constants.MENU;
 import static com.android.tv.testing.uihelper.UiDeviceAsserts.assertWaitForCondition;
 
-import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.support.test.uiautomator.BySelector;
 import android.support.test.uiautomator.UiObject2;
@@ -32,9 +32,8 @@
 import com.android.tv.testing.uihelper.DialogHelper;
 
 @SmallTest
-@SdkSuppress(minSdkVersion = 23)
 public class PlayControlsRowViewTest extends LiveChannelsTestCase {
-    private static final int BUTTON_INDEX_PLAY_PAUSE = 2;
+    private static final String BUTTON_ID_PLAY_PAUSE = "com.android.tv:id/play_pause";
 
     private BySelector mBySettingsSidePanel;
 
@@ -42,7 +41,9 @@
     protected void setUp() throws Exception {
         super.setUp();
         mLiveChannelsHelper.assertAppStarted();
-        pressKeysForChannel(TvTestInputConstants.CH_1_DEFAULT_DONT_MODIFY);
+        pressKeysForChannel(TvTestInputConstants.CH_2);
+        // Wait until KeypadChannelSwitchView closes.
+        assertWaitForCondition(mDevice, Until.hasObject(CHANNEL_BANNER));
         // Tune to a new channel to ensure that the channel is changed.
         mDevice.pressDPadUp();
         getInstrumentation().waitForIdleSync();
@@ -56,7 +57,7 @@
     public void testFocusedViewInNormalCase() {
         mMenuHelper.showMenu();
         mMenuHelper.assertNavigateToPlayControlsRow();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
         mDevice.pressBack();
     }
 
@@ -69,49 +70,30 @@
         // Fast forward button
         mDevice.pressKeyCode(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
         mMenuHelper.assertWaitForMenu();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
         mDevice.pressBack();
 
         // Next button
         mDevice.pressKeyCode(KeyEvent.KEYCODE_MEDIA_NEXT);
         mMenuHelper.assertWaitForMenu();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
-        mDevice.pressBack();
-    }
-
-    /**
-     * Tests the case when the rewinding action is disabled.
-     * In this case, the button corresponding to the action is disabled, so play/pause button should
-     * have the focus.
-     */
-    public void testFocusedViewWithDisabledActionBackward() {
-        // Previous button
-        mDevice.pressKeyCode(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
-        mMenuHelper.assertWaitForMenu();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
-        mDevice.pressBack();
-
-        // Rewind button
-        mDevice.pressKeyCode(KeyEvent.KEYCODE_MEDIA_REWIND);
-        mMenuHelper.assertWaitForMenu();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
         mDevice.pressBack();
     }
 
     public void testFocusedViewInMenu() {
         mMenuHelper.showMenu();
         mDevice.pressKeyCode(KeyEvent.KEYCODE_MEDIA_PLAY);
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
         mMenuHelper.assertNavigateToRow(R.string.menu_title_channels);
         mDevice.pressKeyCode(KeyEvent.KEYCODE_MEDIA_NEXT);
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
     }
 
     public void testKeepPausedWhileParentalControlChange() {
         // Pause the playback.
         mDevice.pressKeyCode(KeyEvent.KEYCODE_MEDIA_PAUSE);
         mMenuHelper.assertWaitForMenu();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
         // Show parental controls fragment.
         mMenuHelper.assertPressOptionsSettings();
         assertWaitForCondition(mDevice, Until.hasObject(mBySettingsSidePanel));
@@ -130,14 +112,14 @@
         mDevice.pressBack();
         // Return to the main menu.
         mMenuHelper.assertWaitForMenu();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
     }
 
     public void testKeepPausedAfterVisitingHome() {
         // Pause the playback.
         mDevice.pressKeyCode(KeyEvent.KEYCODE_MEDIA_PAUSE);
         mMenuHelper.assertWaitForMenu();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
         // Press HOME twice to visit the home screen and return to Live TV.
         mDevice.pressHome();
         // Wait until home screen is shown.
@@ -147,19 +129,15 @@
         mDevice.waitForIdle();
         // Return to the main menu.
         mMenuHelper.assertWaitForMenu();
-        assertButtonHasFocus(BUTTON_INDEX_PLAY_PAUSE);
+        assertButtonHasFocus(BUTTON_ID_PLAY_PAUSE);
     }
 
-    private void assertButtonHasFocus(int expectedButtonIndex) {
+    private void assertButtonHasFocus(String buttonId) {
         UiObject2 menu = mDevice.findObject(MENU);
         UiObject2 focusedView = menu.findObject(FOCUSED_VIEW);
         assertNotNull("Play controls row doesn't have a focused child.", focusedView);
         UiObject2 focusedButtonGroup = focusedView.getParent();
         assertNotNull("The focused item should have parent", focusedButtonGroup);
-        UiObject2 controlBar = focusedButtonGroup.getParent();
-        assertNotNull("The focused item should have grandparent", controlBar);
-        assertTrue("The grandparent should have more than five children",
-                controlBar.getChildCount() >= 5);
-        assertEquals(controlBar.getChildren().get(expectedButtonIndex), focusedButtonGroup);
+        assertEquals(buttonId, focusedButtonGroup.getResourceName());
     }
 }
diff --git a/tests/func/src/com/android/tv/tests/ui/ProgramGuidePerformanceTest.java b/tests/func/src/com/android/tv/tests/ui/ProgramGuidePerformanceTest.java
deleted file mode 100644
index 95921df..0000000
--- a/tests/func/src/com/android/tv/tests/ui/ProgramGuidePerformanceTest.java
+++ /dev/null
@@ -1,59 +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.tests.ui;
-
-import static com.android.tv.testing.uihelper.UiDeviceAsserts.assertWaitForCondition;
-
-import android.os.SystemClock;
-import android.support.test.filters.LargeTest;
-import android.support.test.uiautomator.Until;
-import android.util.Log;
-
-import com.android.tv.R;
-import com.android.tv.testing.uihelper.Constants;
-
-/**
- * Tests for {@link com.android.tv.MainActivity}.
- */
-@LargeTest
-public class ProgramGuidePerformanceTest extends LiveChannelsTestCase {
-    private static final String TAG = "ProgramGuidePerformance";
-
-    public static final int SHOW_MENU_MAX_DURATION_MS = 1500;
-    public void testShowMenu() {
-        mLiveChannelsHelper.assertAppStarted();
-        mMenuHelper.showMenu();
-        mMenuHelper.assertNavigateToMenuItem(R.string.menu_title_channels,
-                R.string.channels_item_program_guide);
-        //TODO: build a simple performance framework like JankTest
-        long start = SystemClock.elapsedRealtime();
-        Log.v(TAG, "start " + start + " milliSeconds");
-        mDevice.pressDPadCenter();
-        assertWaitForCondition(mDevice, Until.hasObject(Constants.PROGRAM_GUIDE));
-        long end = SystemClock.elapsedRealtime();
-        Log.v(TAG, "end " + end + " milliSeconds");
-        long duration = end - start;
-        assertDuration("ShowMenu", SHOW_MENU_MAX_DURATION_MS, duration);
-        mDevice.pressBack();
-    }
-
-    private void assertDuration(String msg, long expectedMaxMilliSeconds, long actualMilliSeconds) {
-        Log.d(TAG, msg + " duration " + actualMilliSeconds + " milliSeconds");
-        assertTrue(msg + " duration expected to be <= " + expectedMaxMilliSeconds
-                + " milliSeconds but was " + actualMilliSeconds + " milliSeconds.",
-                actualMilliSeconds <= expectedMaxMilliSeconds);
-    }
-}
diff --git a/tests/func/src/com/android/tv/tests/ui/dvr/DvrLibraryTest.java b/tests/func/src/com/android/tv/tests/ui/dvr/DvrLibraryTest.java
new file mode 100644
index 0000000..d88e67a
--- /dev/null
+++ b/tests/func/src/com/android/tv/tests/ui/dvr/DvrLibraryTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2017 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.tests.ui.dvr;
+
+import static com.android.tv.testing.uihelper.UiDeviceAsserts.assertHas;
+import static com.android.tv.testing.uihelper.UiDeviceAsserts.assertWaitForCondition;
+import static com.android.tv.testing.uihelper.UiDeviceAsserts.assertWaitUntilFocused;
+
+import android.os.Build;
+import android.support.test.filters.MediumTest;
+import android.support.test.filters.SdkSuppress;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import com.android.tv.R;
+import com.android.tv.testing.uihelper.ByResource;
+import com.android.tv.testing.uihelper.Constants;
+import com.android.tv.tests.ui.LiveChannelsTestCase;
+
+import java.util.regex.Pattern;
+
+@MediumTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public class DvrLibraryTest extends LiveChannelsTestCase {
+    private static final String PROGRAM_NAME_PREFIX = "Title(";
+
+    private BySelector mRecentRow;
+    private BySelector mScheduledRow;
+    private BySelector mSeriesRow;
+    private BySelector mFullScheduleCard;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mRecentRow = By.hasDescendant(ByResource.text(mTargetResources, R.string.dvr_main_recent));
+        mScheduledRow = By.hasDescendant(
+                ByResource.text(mTargetResources, R.string.dvr_main_scheduled));
+        mSeriesRow = By.hasDescendant(ByResource.text(mTargetResources, R.string.dvr_main_series));
+        mFullScheduleCard = By.focusable(true).hasDescendant(
+                ByResource.text(mTargetResources, R.string.dvr_full_schedule_card_view_title));
+        mLiveChannelsHelper.assertAppStarted();
+    }
+
+    public void testCancel() {
+        mMenuHelper.assertPressDvrLibrary();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+        mDevice.pressBack();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+        assertHas(mDevice, Constants.MENU, false);
+    }
+
+    public void testEmptyLibrary() {
+        mMenuHelper.assertPressDvrLibrary();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+
+        // DVR Library is empty, only Scheduled row and Full schedule card should be displayed.
+        assertHas(mDevice, mRecentRow, false);
+        assertHas(mDevice, mScheduledRow, true);
+        assertHas(mDevice, mSeriesRow, false);
+
+        mDevice.pressDPadCenter();
+        assertWaitUntilFocused(mDevice, mFullScheduleCard);
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+
+        // Empty schedules screen should be shown.
+        assertHas(mDevice, Constants.DVR_SCHEDULES, true);
+        assertHas(mDevice, ByResource.text(mTargetResources, R.string.dvr_schedules_empty_state),
+                true);
+
+        // Close the DVR library.
+        mDevice.pressBack();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+        mDevice.pressBack();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+    }
+
+    public void testScheduleRecordings() {
+        BySelector newScheduleCard = By.focusable(true).hasDescendant(
+                By.textStartsWith(PROGRAM_NAME_PREFIX)).hasDescendant(By.textEndsWith("today"));
+        BySelector seriesCardWithOneSchedule = By.focusable(true).hasDescendant(
+                By.textStartsWith(PROGRAM_NAME_PREFIX)).hasDescendant(By.text(mTargetResources
+                        .getQuantityString(R.plurals.dvr_count_scheduled_recordings, 1, 1)));
+        BySelector seriesCardWithOneRecordedProgram = By.focusable(true).hasDescendant(
+                By.textStartsWith(PROGRAM_NAME_PREFIX)).hasDescendant(By.text(mTargetResources
+                        .getQuantityString(R.plurals.dvr_count_new_recordings, 1, 1)));
+        Pattern watchButton = Pattern.compile("^" + mTargetResources
+                .getString(R.string.dvr_detail_watch).toUpperCase() + "\n.*$");
+
+        mMenuHelper.showMenu();
+        mMenuHelper.assertNavigateToPlayControlsRow();
+        mDevice.pressDPadRight();
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.hasObject(
+                ByResource.text(mTargetResources, R.string.dvr_action_record_episode)));
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.gone(
+                ByResource.text(mTargetResources, R.string.dvr_action_record_episode)));
+
+        mMenuHelper.assertPressDvrLibrary();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+
+        // Schedule should be automatically added to the series.
+        assertHas(mDevice, mRecentRow, false);
+        assertHas(mDevice, mScheduledRow, true);
+        assertHas(mDevice, mSeriesRow, true);
+        String programName = mDevice.findObject(By.textStartsWith(PROGRAM_NAME_PREFIX)).getText();
+
+        // Move to scheduled row, there should be one new schedule and one full schedule card.
+        mDevice.pressDPadRight();
+        assertWaitUntilFocused(mDevice, newScheduleCard);
+        mDevice.pressDPadRight();
+        assertWaitUntilFocused(mDevice, mFullScheduleCard);
+
+        // Enters the full schedule, there should be one schedule in the full schedule.
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+        assertHas(mDevice, Constants.DVR_SCHEDULES, true);
+        assertHas(mDevice, ByResource.text(mTargetResources, R.string.dvr_schedules_empty_state),
+                false);
+        assertHas(mDevice, By.textStartsWith(programName), true);
+
+        // Moves to the series card, clicks it, the detail page should be shown with "View schedule"
+        // button.
+        mDevice.pressBack();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+        mDevice.pressDPadLeft();
+        assertWaitUntilFocused(mDevice, newScheduleCard);
+        mDevice.pressDPadDown();
+        assertWaitUntilFocused(mDevice, seriesCardWithOneSchedule);
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+        assertHas(mDevice, By.text(mTargetResources
+                        .getString(R.string.dvr_detail_view_schedule).toUpperCase()), true);
+        assertHas(mDevice, By.text(watchButton), false);
+        assertHas(mDevice, By.text(mTargetResources
+                        .getString(R.string.dvr_detail_series_delete).toUpperCase()), false);
+
+        // Clicks the new schedule, the detail page should be shown with "Stop recording" button.
+        mDevice.pressBack();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+        assertWaitUntilFocused(mDevice, seriesCardWithOneSchedule);
+        mDevice.pressDPadUp();
+        assertWaitUntilFocused(mDevice, newScheduleCard);
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+        assertHas(mDevice, By.text(mTargetResources
+                .getString(R.string.dvr_detail_stop_recording).toUpperCase()), true);
+
+        // Stops the recording
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.hasObject(
+                ByResource.text(mTargetResources, R.string.dvr_action_stop)));
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.gone(
+                ByResource.text(mTargetResources, R.string.dvr_action_stop)));
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+        assertWaitUntilFocused(mDevice, mFullScheduleCard);
+
+        // Moves to series' detail page again, now it should have two more buttons
+        mDevice.pressDPadDown();
+        assertWaitUntilFocused(mDevice, seriesCardWithOneRecordedProgram);
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+        assertHas(mDevice, By.text(watchButton), true);
+        assertHas(mDevice, By.text(mTargetResources
+                .getString(R.string.dvr_detail_view_schedule).toUpperCase()), true);
+        assertHas(mDevice, By.text(mTargetResources
+                .getString(R.string.dvr_detail_series_delete).toUpperCase()), true);
+
+        // Moves to the recent row and clicks the recent recorded program.
+        mDevice.pressBack();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+        assertWaitUntilFocused(mDevice, seriesCardWithOneRecordedProgram);
+        mDevice.pressDPadUp();
+        assertWaitUntilFocused(mDevice, mFullScheduleCard);
+        mDevice.pressDPadUp();
+        assertWaitUntilFocused(mDevice, By.focusable(true).hasDescendant(By.text(programName)));
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+        assertHas(mDevice, By.text(mTargetResources
+                .getString(R.string.dvr_detail_watch).toUpperCase()), true);
+        assertHas(mDevice, By.text(mTargetResources
+                .getString(R.string.dvr_detail_delete).toUpperCase()), true);
+
+        // Moves to the delete button and clicks to remove the recorded program.
+        mDevice.pressDPadRight();
+        assertWaitUntilFocused(mDevice, By.text(mTargetResources
+                .getString(R.string.dvr_detail_delete).toUpperCase()));
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.DVR_LIBRARY));
+        assertWaitUntilFocused(mDevice, mFullScheduleCard);
+
+        // DVR Library should be empty now.
+        assertHas(mDevice, mRecentRow, false);
+        assertHas(mDevice, mScheduledRow, true);
+        assertHas(mDevice, mSeriesRow, false);
+
+        // Close the DVR library.
+        mDevice.pressBack();
+        assertWaitForCondition(mDevice, Until.gone(Constants.DVR_LIBRARY));
+    }
+}
diff --git a/tests/func/src/com/android/tv/tests/ui/sidepanel/CustomizeChannelListFragmentTest.java b/tests/func/src/com/android/tv/tests/ui/sidepanel/CustomizeChannelListFragmentTest.java
new file mode 100644
index 0000000..deeb9bf
--- /dev/null
+++ b/tests/func/src/com/android/tv/tests/ui/sidepanel/CustomizeChannelListFragmentTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 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.tests.ui.sidepanel;
+
+import static com.android.tv.testing.uihelper.UiDeviceAsserts.assertWaitForCondition;
+
+import android.graphics.Point;
+import android.support.test.filters.LargeTest;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+
+import com.android.tv.R;
+import com.android.tv.testing.uihelper.Constants;
+import com.android.tv.tests.ui.LiveChannelsTestCase;
+
+@LargeTest
+public class CustomizeChannelListFragmentTest extends LiveChannelsTestCase {
+    private BySelector mBySettingsSidePanel;
+    private UiObject2 mTvView;
+    private Point mNormalTvViewCenter;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mLiveChannelsHelper.assertAppStarted();
+        mTvView = mDevice.findObject(Constants.TV_VIEW);
+        mNormalTvViewCenter = mTvView.getVisibleCenter();
+        assertNotNull(mNormalTvViewCenter);
+        pressKeysForChannel(com.android.tv.testing.testinput.TvTestInputConstants.CH_2);
+        // Wait until KeypadChannelSwitchView closes.
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.CHANNEL_BANNER));
+        mBySettingsSidePanel = mSidePanelHelper.bySidePanelTitled(
+                R.string.side_panel_title_settings);
+    }
+
+    private void assertShrunkenTvView(boolean shrunkenExpected) {
+        Point currentTvViewCenter = mTvView.getVisibleCenter();
+        if (shrunkenExpected) {
+            assertFalse(mNormalTvViewCenter.equals(currentTvViewCenter));
+        } else {
+            assertTrue(mNormalTvViewCenter.equals(currentTvViewCenter));
+        }
+    }
+
+    public void testCustomizeChannelList_noraml() {
+        // Show customize channel list fragment
+        mMenuHelper.assertPressOptionsSettings();
+        assertWaitForCondition(mDevice, Until.hasObject(mBySettingsSidePanel));
+        mSidePanelHelper.assertNavigateToItem(
+                R.string.settings_channel_source_item_customize_channels);
+        mDevice.pressDPadCenter();
+        BySelector bySidePanel = mSidePanelHelper.bySidePanelTitled(
+                R.string.side_panel_title_edit_channels_for_an_input);
+        assertWaitForCondition(mDevice, Until.hasObject(bySidePanel));
+        assertShrunkenTvView(true);
+
+        // Show group by fragment
+        mSidePanelHelper.assertNavigateToItem(R.string.edit_channels_item_group_by, Direction.UP);
+        mDevice.pressDPadCenter();
+        bySidePanel = mSidePanelHelper.bySidePanelTitled(R.string.side_panel_title_group_by);
+        assertWaitForCondition(mDevice, Until.hasObject(bySidePanel));
+        assertShrunkenTvView(true);
+
+        // Back to customize channel list fragment
+        mDevice.pressBack();
+        bySidePanel = mSidePanelHelper.bySidePanelTitled(
+                R.string.side_panel_title_edit_channels_for_an_input);
+        assertWaitForCondition(mDevice, Until.hasObject(bySidePanel));
+        assertShrunkenTvView(true);
+
+        // Return to the main menu.
+        mDevice.pressBack();
+        assertWaitForCondition(mDevice, Until.hasObject(mBySettingsSidePanel));
+        assertShrunkenTvView(false);
+    }
+
+    public void testCustomizeChannelList_timeout() {
+        // Show customize channel list fragment
+        mMenuHelper.assertPressOptionsSettings();
+        assertWaitForCondition(mDevice, Until.hasObject(mBySettingsSidePanel));
+        mSidePanelHelper.assertNavigateToItem(
+                R.string.settings_channel_source_item_customize_channels);
+        mDevice.pressDPadCenter();
+        BySelector bySidePanel = mSidePanelHelper.bySidePanelTitled(
+                R.string.side_panel_title_edit_channels_for_an_input);
+        assertWaitForCondition(mDevice, Until.hasObject(bySidePanel));
+        assertShrunkenTvView(true);
+
+        // Show group by fragment
+        mSidePanelHelper.assertNavigateToItem(R.string.edit_channels_item_group_by, Direction.UP);
+        mDevice.pressDPadCenter();
+        bySidePanel = mSidePanelHelper.bySidePanelTitled(R.string.side_panel_title_group_by);
+        assertWaitForCondition(mDevice, Until.hasObject(bySidePanel));
+        assertShrunkenTvView(true);
+
+        // Wait for time-out to return to the main menu.
+        assertWaitForCondition(mDevice, Until.gone(bySidePanel),
+                mTargetResources.getInteger(R.integer.side_panel_show_duration));
+        assertShrunkenTvView(false);
+    }
+}
diff --git a/tests/input/OWNERS b/tests/input/OWNERS
new file mode 100644
index 0000000..4aa5fe5
--- /dev/null
+++ b/tests/input/OWNERS
@@ -0,0 +1,2 @@
+nchalko@google.com
+shubang@google.com
diff --git a/tests/input/res/values/strings.xml b/tests/input/res/values/strings.xml
index 3f2ab3f..4ef4395 100644
--- a/tests/input/res/values/strings.xml
+++ b/tests/input/res/values/strings.xml
@@ -15,7 +15,6 @@
   -->
 <resources>
     <string name="app_name" translatable="false">Test TV Inputs</string>
-    <string name="about_app" translatable="false">About TV Test Inputs</string>
     <string name="version" translatable="false">Version: %1$s</string>
     <string name="sample_tv_input" translatable="false">Test TV Input</string>
     <string name="simple_input_label" translatable="false">Test Input</string>
diff --git a/tests/input/src/com/android/tv/testinput/TestTvInputService.java b/tests/input/src/com/android/tv/testinput/TestTvInputService.java
index 659b341..621ceac 100644
--- a/tests/input/src/com/android/tv/testinput/TestTvInputService.java
+++ b/tests/input/src/com/android/tv/testinput/TestTvInputService.java
@@ -326,11 +326,16 @@
                     if (currentSurface != null) {
                         String now = new Date(mCurrentPositionMs).toString();
                         String name = currentChannel == null ? "Null" : currentChannel.name;
-                        Canvas c = currentSurface.lockCanvas(null);
-                        c.drawColor(0xFF888888);
-                        c.drawText(name, 100f, 200f, mTextPaint);
-                        c.drawText(now, 100f, 400f, mTextPaint);
-                        currentSurface.unlockCanvasAndPost(c);
+                        try {
+                            Canvas c = currentSurface.lockCanvas(null);
+                            c.drawColor(0xFF888888);
+                            c.drawText(name, 100f, 200f, mTextPaint);
+                            c.drawText(now, 100f, 400f, mTextPaint);
+                            // Assuming c.drawXXX will never fail.
+                            currentSurface.unlockCanvasAndPost(c);
+                        } catch (IllegalArgumentException e) {
+                            // The surface might have been abandoned. Ignore the exception.
+                        }
                         if (DEBUG) {
                             Log.v(TAG, "Post to canvas");
                         }
diff --git a/tests/input/src/com/android/tv/testinput/TestTvInputSetupActivity.java b/tests/input/src/com/android/tv/testinput/TestTvInputSetupActivity.java
index 732972c..a793ac7 100644
--- a/tests/input/src/com/android/tv/testinput/TestTvInputSetupActivity.java
+++ b/tests/input/src/com/android/tv/testinput/TestTvInputSetupActivity.java
@@ -20,13 +20,10 @@
 import android.app.AlertDialog;
 import android.app.Dialog;
 import android.app.DialogFragment;
-import android.content.ContentResolver;
-import android.content.ContentValues;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.media.tv.TvContract;
 import android.media.tv.TvInputInfo;
-import android.net.Uri;
 import android.os.Bundle;
 import android.util.Log;
 
@@ -58,39 +55,27 @@
 
     private void registerChannels(int channelCount) {
         TestTvInputSetupActivity context = this;
-        registerChannels(context, mInputId, false, channelCount);
+        registerChannels(context, mInputId, channelCount);
     }
 
-    public static void registerChannels(Context context, String inputId, boolean updateBrowsable,
-            int channelCount) {
+    public static void registerChannels(Context context, String inputId, int channelCount) {
         Log.i(TAG, "Registering " + channelCount + " channels");
         List<ChannelInfo> channels = new ArrayList<>();
         for (int i = 1; i <= channelCount; i++) {
             channels.add(ChannelInfo.create(context, i));
         }
         ChannelUtils.updateChannels(context, inputId, channels);
-        if (updateBrowsable) {
-            updateChannelsBrowsable(context.getContentResolver(), inputId);
-        }
 
         // Reload channels so we have the ids.
         Map<Long, ChannelInfo> channelIdToInfoMap =
                 ChannelUtils.queryChannelInfoMapForTvInput(context, inputId);
         for (Long channelId : channelIdToInfoMap.keySet()) {
-            // TODO: http://b/21705569 Create better program info for tests
             ProgramInfo programInfo = ProgramInfo.create();
             ProgramUtils.populatePrograms(context, TvContract.buildChannelUri(channelId),
                     programInfo);
         }
     }
 
-    private static void updateChannelsBrowsable(ContentResolver contentResolver, String inputId) {
-        Uri uri = TvContract.buildChannelsUriForInput(inputId);
-        ContentValues values = new ContentValues();
-        values.put(TvContract.Channels.COLUMN_BROWSABLE, 1);
-        contentResolver.update(uri, values, null, null);
-    }
-
     public static class MyAlertDialogFragment extends DialogFragment {
         @Override
         public Dialog onCreateDialog(Bundle savedInstanceState) {
diff --git a/tests/input/src/com/android/tv/testinput/instrument/TestSetupInstrumentation.java b/tests/input/src/com/android/tv/testinput/instrument/TestSetupInstrumentation.java
index 379bce8..48e485c 100644
--- a/tests/input/src/com/android/tv/testinput/instrument/TestSetupInstrumentation.java
+++ b/tests/input/src/com/android/tv/testinput/instrument/TestSetupInstrumentation.java
@@ -104,7 +104,7 @@
                     throw new TestSetupException(
                             "Unknown " + TEST_SETUP_MODE_ARG + " of " + testSetupMode);
             }
-            TestTvInputSetupActivity.registerChannels(getContext(), mInputId, true, channelCount);
+            TestTvInputSetupActivity.registerChannels(getContext(), mInputId, channelCount);
         }
     }
 
diff --git a/tests/jank/Android.mk b/tests/jank/Android.mk
index 210a75e..b71ea1b 100644
--- a/tests/jank/Android.mk
+++ b/tests/jank/Android.mk
@@ -15,8 +15,6 @@
     ub-janktesthelper \
     ub-uiautomator \
 
-LOCAL_JAVA_LIBRARIES := legacy-android-test
-
 LOCAL_INSTRUMENTATION_FOR := LiveTv
 
 LOCAL_SDK_VERSION := current
diff --git a/tests/jank/OWNERS b/tests/jank/OWNERS
new file mode 100644
index 0000000..4aa5fe5
--- /dev/null
+++ b/tests/jank/OWNERS
@@ -0,0 +1,2 @@
+nchalko@google.com
+shubang@google.com
diff --git a/tests/jank/src/com/android/tv/tests/jank/ChannelZappingJankTest.java b/tests/jank/src/com/android/tv/tests/jank/ChannelZappingJankTest.java
index b0463e7..ef936e3 100644
--- a/tests/jank/src/com/android/tv/tests/jank/ChannelZappingJankTest.java
+++ b/tests/jank/src/com/android/tv/tests/jank/ChannelZappingJankTest.java
@@ -15,20 +15,15 @@
  */
 package com.android.tv.tests.jank;
 
-import android.content.res.Resources;
 import android.support.test.filters.MediumTest;
 import android.support.test.jank.GfxMonitor;
 import android.support.test.jank.JankTest;
-import android.support.test.jank.JankTestBase;
-import android.support.test.uiautomator.UiDevice;
-
-import com.android.tv.testing.uihelper.LiveChannelsUiDeviceHelper;
 
 /**
  * Jank tests for channel zapping.
  */
 @MediumTest
-public class ChannelZappingJankTest extends JankTestBase {
+public class ChannelZappingJankTest extends LiveChannelsTestCase {
     private static final String TAG = "ChannelZappingJankTest";
 
     private static final String STARTING_CHANNEL = "13";
@@ -45,16 +40,9 @@
     private static final int EXPECTED_FRAMES = 100;
     private static final int WARM_UP_CHANNEL_ZAPPING_COUNT = 2;
 
-    private UiDevice mDevice;
-
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mDevice = UiDevice.getInstance(getInstrumentation());
-        Resources targetResources = getInstrumentation().getTargetContext().getResources();
-        LiveChannelsUiDeviceHelper liveChannelsHelper = new LiveChannelsUiDeviceHelper(mDevice,
-                targetResources, getInstrumentation().getContext());
-        liveChannelsHelper.assertAppStarted();
         Utils.pressKeysForChannelNumber(STARTING_CHANNEL, mDevice);
     }
 
diff --git a/tests/jank/src/com/android/tv/tests/jank/LiveChannelsTestCase.java b/tests/jank/src/com/android/tv/tests/jank/LiveChannelsTestCase.java
new file mode 100644
index 0000000..6de0103
--- /dev/null
+++ b/tests/jank/src/com/android/tv/tests/jank/LiveChannelsTestCase.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 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.tests.jank;
+
+import android.content.res.Resources;
+import android.support.test.jank.JankTestBase;
+import android.support.test.uiautomator.UiDevice;
+
+import com.android.tv.testing.uihelper.LiveChannelsUiDeviceHelper;
+
+/**
+ * Base test case for LiveChannel jank tests.
+ */
+abstract class LiveChannelsTestCase extends JankTestBase {
+    protected UiDevice mDevice;
+    protected Resources mTargetResources;
+    protected LiveChannelsUiDeviceHelper mLiveChannelsHelper;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance(getInstrumentation());
+        mTargetResources = getInstrumentation().getTargetContext().getResources();
+        mLiveChannelsHelper = new LiveChannelsUiDeviceHelper(mDevice, mTargetResources,
+                getInstrumentation().getContext());
+        mLiveChannelsHelper.assertAppStarted();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        // Destroys the activity to make sure next test case's activity launch check works well.
+        mLiveChannelsHelper.assertAppStopped();
+        super.tearDown();
+    }
+}
diff --git a/tests/jank/src/com/android/tv/tests/jank/MenuJankTest.java b/tests/jank/src/com/android/tv/tests/jank/MenuJankTest.java
index 47ebea3..411a0bb 100644
--- a/tests/jank/src/com/android/tv/tests/jank/MenuJankTest.java
+++ b/tests/jank/src/com/android/tv/tests/jank/MenuJankTest.java
@@ -15,21 +15,17 @@
  */
 package com.android.tv.tests.jank;
 
-import android.content.res.Resources;
 import android.support.test.filters.MediumTest;
 import android.support.test.jank.GfxMonitor;
 import android.support.test.jank.JankTest;
-import android.support.test.jank.JankTestBase;
-import android.support.test.uiautomator.UiDevice;
 
-import com.android.tv.testing.uihelper.LiveChannelsUiDeviceHelper;
 import com.android.tv.testing.uihelper.MenuHelper;
 
 /**
  * Jank tests for the program guide.
  */
 @MediumTest
-public class MenuJankTest extends JankTestBase {
+public class MenuJankTest extends LiveChannelsTestCase {
     private static final String STARTING_CHANNEL = "1";
 
     /**
@@ -42,22 +38,12 @@
      * @see <a href="http://go/janktesthelper-best-practices">Jank Test Helper Best Practices</a>
      */
     private static final int EXPECTED_FRAMES = 200;
-
-    protected UiDevice mDevice;
-
-    protected Resources mTargetResources;
     protected MenuHelper mMenuHelper;
-    protected LiveChannelsUiDeviceHelper mLiveChannelsHelper;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mDevice = UiDevice.getInstance(getInstrumentation());
-        mTargetResources = getInstrumentation().getTargetContext().getResources();
         mMenuHelper = new MenuHelper(mDevice, mTargetResources);
-        mLiveChannelsHelper = new LiveChannelsUiDeviceHelper(mDevice, mTargetResources,
-                getInstrumentation().getContext());
-        mLiveChannelsHelper.assertAppStarted();
         Utils.pressKeysForChannelNumber(STARTING_CHANNEL, mDevice);
     }
 
diff --git a/tests/jank/src/com/android/tv/tests/jank/ProgramGuideJankTest.java b/tests/jank/src/com/android/tv/tests/jank/ProgramGuideJankTest.java
index 7d751c4..d8860dd 100644
--- a/tests/jank/src/com/android/tv/tests/jank/ProgramGuideJankTest.java
+++ b/tests/jank/src/com/android/tv/tests/jank/ProgramGuideJankTest.java
@@ -17,29 +17,21 @@
 
 import static com.android.tv.testing.uihelper.UiDeviceAsserts.assertWaitForCondition;
 
-import android.content.res.Resources;
 import android.support.test.filters.MediumTest;
 import android.support.test.jank.GfxMonitor;
 import android.support.test.jank.JankTest;
-import android.support.test.jank.JankTestBase;
-import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.Until;
 
 import com.android.tv.R;
 import com.android.tv.testing.uihelper.ByResource;
 import com.android.tv.testing.uihelper.Constants;
-import com.android.tv.testing.uihelper.LiveChannelsUiDeviceHelper;
 import com.android.tv.testing.uihelper.MenuHelper;
-import com.android.tv.testing.uihelper.UiDeviceUtils;
 
 /**
  * Jank tests for the program guide.
  */
 @MediumTest
-public class ProgramGuideJankTest extends JankTestBase {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "ProgramGuideJank";
-
+public class ProgramGuideJankTest extends LiveChannelsTestCase {
     private static final String STARTING_CHANNEL = "13";
 
     /**
@@ -53,20 +45,12 @@
      */
     private static final int EXPECTED_FRAMES = 200;
 
-    private UiDevice mDevice;
-
-    private Resources mTargetResources;
     private MenuHelper mMenuHelper;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mDevice = UiDevice.getInstance(getInstrumentation());
-        mTargetResources = getInstrumentation().getTargetContext().getResources();
         mMenuHelper = new MenuHelper(mDevice, mTargetResources);
-        LiveChannelsUiDeviceHelper liveChannelsHelper = new LiveChannelsUiDeviceHelper(mDevice,
-                mTargetResources, getInstrumentation().getContext());
-        liveChannelsHelper.assertAppStarted();
         Utils.pressKeysForChannelNumber(STARTING_CHANNEL, mDevice);
     }
 
@@ -83,7 +67,7 @@
     }
 
     @JankTest(expectedFrames = EXPECTED_FRAMES,
-            beforeLoop = "showProgramGuide",
+            beforeLoop = "showAndFocusProgramGuide",
             afterLoop = "clearProgramGuide")
     @GfxMonitor(processName = Utils.LIVE_CHANNELS_PROCESS_NAME)
     public void testScrollDown() {
@@ -95,7 +79,7 @@
     }
 
     @JankTest(expectedFrames = EXPECTED_FRAMES,
-            beforeLoop = "showProgramGuide",
+            beforeLoop = "showAndFocusProgramGuide",
             afterLoop = "clearProgramGuide")
     @GfxMonitor(processName = Utils.LIVE_CHANNELS_PROCESS_NAME)
     public void testScrollRight() {
@@ -128,11 +112,17 @@
         assertWaitForCondition(mDevice, Until.gone(Constants.PROGRAM_GUIDE));
     }
 
-    // It's public to be used with @JankTest annotation.
     public void showProgramGuide() {
         selectProgramGuideMenuItem();
         mDevice.pressDPadCenter();
         assertWaitForCondition(mDevice, Until.hasObject(Constants.PROGRAM_GUIDE));
+    }
+
+    // It's public to be used with @JankTest annotation.
+    public void showAndFocusProgramGuide() {
+        selectProgramGuideMenuItem();
+        mDevice.pressDPadCenter();
+        assertWaitForCondition(mDevice, Until.hasObject(Constants.PROGRAM_GUIDE));
         // If the side panel grid is visible (and thus has focus), move right to clear it.
         if (mDevice.hasObject(
                 ByResource.id(mTargetResources, R.id.program_guide_side_panel_grid_view))) {
diff --git a/tests/unit/Android.mk b/tests/unit/Android.mk
index f53220d..3632fe9 100644
--- a/tests/unit/Android.mk
+++ b/tests/unit/Android.mk
@@ -12,7 +12,8 @@
     mockito-target \
     tv-test-common \
 
-LOCAL_JAVA_LIBRARIES := android.test.mock.sdk legacy-android-test
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/../common/res
 
 LOCAL_PACKAGE_NAME := TVUnitTests
 
@@ -22,3 +23,4 @@
 LOCAL_MIN_SDK_VERSION := 23  # M
 
 include $(BUILD_PACKAGE)
+
diff --git a/tests/unit/AndroidManifest.xml b/tests/unit/AndroidManifest.xml
index aebb377..d073f8a 100644
--- a/tests/unit/AndroidManifest.xml
+++ b/tests/unit/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.tv.tests" >
 
-    <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="21" />
+    <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="23" />
 
     <instrumentation
         android:name="android.support.test.runner.AndroidJUnitRunner"
diff --git a/tests/unit/OWNERS b/tests/unit/OWNERS
new file mode 100644
index 0000000..4aa5fe5
--- /dev/null
+++ b/tests/unit/OWNERS
@@ -0,0 +1,2 @@
+nchalko@google.com
+shubang@google.com
diff --git a/tests/unit/src/com/android/tv/BaseMainActivityTestCase.java b/tests/unit/src/com/android/tv/BaseMainActivityTestCase.java
index e2f620e..e6f1af7 100644
--- a/tests/unit/src/com/android/tv/BaseMainActivityTestCase.java
+++ b/tests/unit/src/com/android/tv/BaseMainActivityTestCase.java
@@ -15,9 +15,11 @@
  */
 package com.android.tv;
 
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+
 import android.content.Context;
 import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase2;
+import android.support.test.rule.ActivityTestRule;
 import android.text.TextUtils;
 
 import com.android.tv.data.Channel;
@@ -28,41 +30,40 @@
 import com.android.tv.testing.testinput.TestInputControlUtils;
 import com.android.tv.testing.testinput.TvTestInputConstants;
 
+import org.junit.Before;
+import org.junit.Rule;
+
 import java.util.List;
 
 /**
  * Base TestCase for tests that need a {@link MainActivity}.
  */
-public abstract class BaseMainActivityTestCase
-        extends ActivityInstrumentationTestCase2<MainActivity> {
+public abstract class BaseMainActivityTestCase {
     private static final String TAG = "BaseMainActivityTest";
     private static final int CHANNEL_LOADING_CHECK_INTERVAL_MS = 10;
 
+    @Rule
+    public ActivityTestRule<MainActivity> mActivityTestRule =
+            new ActivityTestRule<>(MainActivity.class);
+
     protected final TestInputControlConnection mConnection = new TestInputControlConnection();
 
     protected MainActivity mActivity;
 
-    public BaseMainActivityTestCase(Class<MainActivity> activityClass) {
-        super(activityClass);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
+        mActivity = mActivityTestRule.getActivity();
         // TODO: ensure the SampleInputs are setup.
-        setActivityInitialTouchMode(false);
-        mActivity = getActivity();
-        getInstrumentation().getContext()
+        getInstrumentation().getTargetContext()
                 .bindService(TestInputControlUtils.createIntent(), mConnection,
                         Context.BIND_AUTO_CREATE);
     }
 
-    @Override
-    protected void tearDown() throws Exception {
+    @Before
+    public void tearDown() {
         if (mConnection.isBound()) {
-            getInstrumentation().getContext().unbindService(mConnection);
+            getInstrumentation().getTargetContext().unbindService(mConnection);
         }
-        super.tearDown();
     }
 
     /**
@@ -72,16 +73,12 @@
      */
     protected void tuneToChannel(final Channel channel) {
         // Run on UI thread so views can be modified
-        try {
-            runTestOnUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    mActivity.tuneToChannel(channel);
-                }
-            });
-        } catch (Throwable throwable) {
-            throw new RuntimeException(throwable);
-        }
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mActivity.tuneToChannel(channel);
+            }
+        });
     }
 
     /**
@@ -130,13 +127,17 @@
 
     private Channel findChannelWithName(String displayName) {
         waitUntilChannelLoadingFinish();
-        List<Channel> channelList = mActivity.getChannelDataManager().getChannelList();
+        Channel channel = null;
+        List <Channel> channelList = mActivity.getChannelDataManager().getChannelList();
         for (Channel c : channelList) {
             if (TextUtils.equals(c.getDisplayName(), displayName)) {
-                return c;
+                channel = c;
+                break;
             }
         }
-        throw new AssertionError("'" + displayName + "' channel not found");
+        if (channel == null) {
+            throw new AssertionError("'" + displayName + "' channel not found");
+        }
+        return channel;
     }
-
 }
diff --git a/tests/unit/src/com/android/tv/CurrentPositionMediatorTest.java b/tests/unit/src/com/android/tv/CurrentPositionMediatorTest.java
index 899083f..f291718 100644
--- a/tests/unit/src/com/android/tv/CurrentPositionMediatorTest.java
+++ b/tests/unit/src/com/android/tv/CurrentPositionMediatorTest.java
@@ -18,33 +18,37 @@
 
 import static com.android.tv.TimeShiftManager.INVALID_TIME;
 import static com.android.tv.TimeShiftManager.REQUEST_TIMEOUT_MS;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
 
+import android.support.test.annotation.UiThreadTest;
 import android.support.test.filters.MediumTest;
-import android.test.UiThreadTest;
+
+import org.junit.Before;
+import org.junit.Test;
 
 @MediumTest
 public class CurrentPositionMediatorTest extends BaseMainActivityTestCase {
     private TimeShiftManager.CurrentPositionMediator mMediator;
 
-    public CurrentPositionMediatorTest() {
-        super(MainActivity.class);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @Before
+    public void setUp() {
         super.setUp();
         mMediator = mActivity.getTimeShiftManager().mCurrentPositionMediator;
     }
 
     @UiThreadTest
-    public void testInitialize() throws Throwable {
+    @Test
+    public void testInitialize() {
         long currentTimeMs = System.currentTimeMillis();
         mMediator.initialize(currentTimeMs);
         assertCurrentPositionMediator(INVALID_TIME, currentTimeMs);
     }
 
     @UiThreadTest
-    public void testOnSeekRequested() throws Throwable {
+    @Test
+    public void testOnSeekRequested() {
         long seekToTimeMs = System.currentTimeMillis() - REQUEST_TIMEOUT_MS * 3;
         mMediator.onSeekRequested(seekToTimeMs);
         assertNotSame("Seek request time", INVALID_TIME, mMediator.mSeekRequestTimeMs);
@@ -52,7 +56,8 @@
     }
 
     @UiThreadTest
-    public void testOnCurrentPositionChangedInvalidInput() throws Throwable {
+    @Test
+    public void testOnCurrentPositionChangedInvalidInput() {
         long seekToTimeMs = System.currentTimeMillis() - REQUEST_TIMEOUT_MS * 3;
         long newCurrentTimeMs = seekToTimeMs + REQUEST_TIMEOUT_MS;
         mMediator.onSeekRequested(seekToTimeMs);
@@ -63,7 +68,8 @@
     }
 
     @UiThreadTest
-    public void testOnCurrentPositionChangedValidInput() throws Throwable {
+    @Test
+    public void testOnCurrentPositionChangedValidInput() {
         long seekToTimeMs = System.currentTimeMillis() - REQUEST_TIMEOUT_MS * 3;
         long newCurrentTimeMs = seekToTimeMs + REQUEST_TIMEOUT_MS - 1;
         mMediator.onSeekRequested(seekToTimeMs);
diff --git a/tests/unit/src/com/android/tv/FeaturesTest.java b/tests/unit/src/com/android/tv/FeaturesTest.java
index 644c424..9d61e75 100644
--- a/tests/unit/src/com/android/tv/FeaturesTest.java
+++ b/tests/unit/src/com/android/tv/FeaturesTest.java
@@ -16,19 +16,21 @@
 
 package com.android.tv;
 
+import static org.junit.Assert.assertFalse;
+
 import android.support.test.filters.SmallTest;
 
-import junit.framework.TestCase;
+import org.junit.Test;
 
 /**
  * Test for features.
  */
 @SmallTest
-public class FeaturesTest extends TestCase {
-
+public class FeaturesTest {
+    @Test
     public void testPropertyFeatureKeyLength() {
         // This forces the class to be loaded and verifies all PropertyFeature key lengths.
         // If any keys are too long the test will fail to load.
-        assertEquals(false, Features.TEST_FEATURE.isEnabled(null));
+        assertFalse(Features.TEST_FEATURE.isEnabled(null));
     }
 }
diff --git a/tests/unit/src/com/android/tv/MainActivityTest.java b/tests/unit/src/com/android/tv/MainActivityTest.java
index b2fe674..1580503 100644
--- a/tests/unit/src/com/android/tv/MainActivityTest.java
+++ b/tests/unit/src/com/android/tv/MainActivityTest.java
@@ -15,6 +15,10 @@
  */
 package com.android.tv;
 
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
 import android.support.test.filters.MediumTest;
 import android.view.View;
 import android.widget.TextView;
@@ -23,6 +27,8 @@
 import com.android.tv.testing.testinput.TvTestInputConstants;
 import com.android.tv.ui.ChannelBannerView;
 
+import org.junit.Test;
+
 import java.util.List;
 
 /**
@@ -30,25 +36,22 @@
  */
 @MediumTest
 public class MainActivityTest extends BaseMainActivityTestCase {
-
-    public MainActivityTest() {
-        super(MainActivity.class);
-    }
-
+    @Test
     public void testInitialConditions() {
         waitUntilChannelLoadingFinish();
         List<Channel> channelList = mActivity.getChannelDataManager().getChannelList();
         assertTrue("Expected at least one channel", channelList.size() > 0);
-        assertFalse("PIP disabled", mActivity.isPipEnabled());
     }
 
-    public void testTuneToChannel() throws Throwable {
+    @Test
+    public void testTuneToChannel() {
         tuneToChannel(TvTestInputConstants.CH_2);
         assertChannelBannerShown(true);
         assertChannelName(TvTestInputConstants.CH_2.name);
     }
 
-    public void testShowProgramGuide() throws Throwable {
+    @Test
+    public void testShowProgramGuide() {
         tuneToChannel(TvTestInputConstants.CH_2);
         showProgramGuide();
         getInstrumentation().waitForIdleSync();
@@ -56,7 +59,7 @@
         assertProgramGuide(true);
     }
 
-    private void showProgramGuide() throws Throwable {
+    private void showProgramGuide() {
         // Run on UI thread so views can be modified
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
@@ -81,7 +84,7 @@
     }
 
     private View assertExpectedBannerSceneClassShown(Class<ChannelBannerView> expectedClass,
-            boolean expectedShown) throws AssertionError {
+            boolean expectedShown) {
         View v = assertViewIsShown(expectedClass.getSimpleName(), R.id.scene_transition_common,
                 expectedShown);
         if (v != null) {
@@ -90,8 +93,7 @@
         return v;
     }
 
-    private View assertViewIsShown(String viewName, int viewId, boolean expected)
-            throws AssertionError {
+    private View assertViewIsShown(String viewName, int viewId, boolean expected) {
         View view = mActivity.findViewById(viewId);
         if (view == null) {
             if (expected) {
@@ -103,5 +105,4 @@
         assertEquals(viewName + " shown", expected, view.isShown());
         return view;
     }
-
 }
diff --git a/tests/unit/src/com/android/tv/TimeShiftManagerTest.java b/tests/unit/src/com/android/tv/TimeShiftManagerTest.java
index f7c6f62..052b5d1 100644
--- a/tests/unit/src/com/android/tv/TimeShiftManagerTest.java
+++ b/tests/unit/src/com/android/tv/TimeShiftManagerTest.java
@@ -22,23 +22,25 @@
 import static com.android.tv.TimeShiftManager.TIME_SHIFT_ACTION_ID_PAUSE;
 import static com.android.tv.TimeShiftManager.TIME_SHIFT_ACTION_ID_PLAY;
 import static com.android.tv.TimeShiftManager.TIME_SHIFT_ACTION_ID_REWIND;
+import static org.junit.Assert.assertEquals;
 
 import android.support.test.filters.MediumTest;
 
+import org.junit.Before;
+import org.junit.Test;
+
 @MediumTest
 public class TimeShiftManagerTest extends BaseMainActivityTestCase {
     private TimeShiftManager mTimeShiftManager;
 
-    public TimeShiftManagerTest() {
-        super(MainActivity.class);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @Before
+    public void setUp() {
         super.setUp();
         mTimeShiftManager = mActivity.getTimeShiftManager();
     }
 
+    @Test
     public void testDisableActions() {
         enableAllActions(true);
         assertActionState(true, true, true, true, true, true);
@@ -56,6 +58,7 @@
         assertActionState(false, false, false, false, false, false);
     }
 
+    @Test
     public void testEnableActions() {
         enableAllActions(false);
         assertActionState(false, false, false, false, false, false);
diff --git a/tests/unit/src/com/android/tv/common/TvContentRatingCacheTest.java b/tests/unit/src/com/android/tv/common/TvContentRatingCacheTest.java
deleted file mode 100644
index eadc50d..0000000
--- a/tests/unit/src/com/android/tv/common/TvContentRatingCacheTest.java
+++ /dev/null
@@ -1,172 +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.common;
-
-import android.content.ComponentCallbacks2;
-import android.media.tv.TvContentRating;
-import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
-import android.test.MoreAsserts;
-
-import com.android.tv.testing.TvContentRatingConstants;
-import com.android.tv.util.Utils;
-
-/**
- * Test for {@link android.media.tv.TvContentRating} tests in {@link Utils}.
- */
-@SmallTest
-public class TvContentRatingCacheTest extends AndroidTestCase {
-
-    /**
-     * US_TV_MA and US_TV_Y7 in order
-     */
-    public static final String MA_AND_Y7 = TvContentRatingConstants.STRING_US_TV_MA + ","
-            + TvContentRatingConstants.STRING_US_TV_Y7_US_TV_FV;
-
-    /**
-     * US_TV_MA and US_TV_Y7 not in order
-     */
-    public static final String Y7_AND_MA = TvContentRatingConstants.STRING_US_TV_Y7_US_TV_FV + ","
-            + TvContentRatingConstants.STRING_US_TV_MA;
-    final TvContentRatingCache mCache = TvContentRatingCache.getInstance();
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mCache.performTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mCache.performTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-        super.tearDown();
-    }
-
-    public void testGetRatings_US_TV_MA() {
-        TvContentRating[] result = mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        MoreAsserts.assertEquals(asArray(TvContentRatingConstants.CONTENT_RATING_US_TV_MA), result);
-    }
-
-    public void testGetRatings_US_TV_MA_same() {
-        TvContentRating[] first = mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        TvContentRating[] second = mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        assertSame(first, second);
-    }
-
-    public void testGetRatings_US_TV_MA_diffAfterClear() {
-        TvContentRating[] first = mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        mCache.performTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
-        TvContentRating[] second = mCache.getRatings(TvContentRatingConstants.STRING_US_TV_MA);
-        assertNotSame(first, second);
-    }
-
-    public void testGetRatings_TWO_orderDoesNotMatter() {
-        TvContentRating[] first = mCache.getRatings(MA_AND_Y7);
-        TvContentRating[] second = mCache.getRatings(Y7_AND_MA);
-        assertSame(first, second);
-    }
-
-    public void testContentRatingsToString_null() {
-        String result = TvContentRatingCache.contentRatingsToString(null);
-        assertEquals("ratings string", null, result);
-    }
-
-    public void testContentRatingsToString_none() {
-        String result = TvContentRatingCache.contentRatingsToString(asArray());
-        assertEquals("ratings string", null, result);
-    }
-
-    public void testContentRatingsToString_one() {
-        String result = TvContentRatingCache
-                .contentRatingsToString(asArray(TvContentRatingConstants.CONTENT_RATING_US_TV_MA));
-        assertEquals("ratings string", TvContentRatingConstants.STRING_US_TV_MA, result);
-    }
-
-    public void testContentRatingsToString_twoInOrder() {
-        String result = TvContentRatingCache.contentRatingsToString(
-                asArray(TvContentRatingConstants.CONTENT_RATING_US_TV_MA,
-                        TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV));
-        assertEquals("ratings string", MA_AND_Y7, result);
-    }
-
-    public void testContentRatingsToString_twoNotInOrder() {
-        String result = TvContentRatingCache.contentRatingsToString(asArray(
-                TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV,
-                TvContentRatingConstants.CONTENT_RATING_US_TV_MA));
-        assertEquals("ratings string", MA_AND_Y7, result);
-    }
-
-    public void testContentRatingsToString_double() {
-        String result = TvContentRatingCache.contentRatingsToString(asArray(
-                TvContentRatingConstants.CONTENT_RATING_US_TV_MA,
-                TvContentRatingConstants.CONTENT_RATING_US_TV_MA));
-        assertEquals("ratings string", TvContentRatingConstants.STRING_US_TV_MA, result);
-    }
-
-    public void testStringToContentRatings_null() {
-        assertNull(TvContentRatingCache.stringToContentRatings(null));
-    }
-
-    public void testStringToContentRatings_none() {
-        assertNull(TvContentRatingCache.stringToContentRatings(""));
-    }
-
-    public void testStringToContentRatings_bad() {
-        assertNull(TvContentRatingCache.stringToContentRatings("bad"));
-    }
-
-    public void testStringToContentRatings_oneGoodOneBad() {
-        TvContentRating[] results = TvContentRatingCache
-                .stringToContentRatings(TvContentRatingConstants.STRING_US_TV_Y7_US_TV_FV + ",bad");
-        MoreAsserts.assertEquals("ratings",
-                asArray(TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV), results);
-    }
-
-    public void testStringToContentRatings_one() {
-        TvContentRating[] results = TvContentRatingCache
-                .stringToContentRatings(TvContentRatingConstants.STRING_US_TV_Y7_US_TV_FV);
-        MoreAsserts.assertEquals("ratings",
-                asArray(TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV), results);
-    }
-
-    public void testStringToContentRatings_twoNotInOrder() {
-        TvContentRating[] results = TvContentRatingCache.stringToContentRatings(Y7_AND_MA);
-        MoreAsserts.assertEquals("ratings",
-                asArray(TvContentRatingConstants.CONTENT_RATING_US_TV_MA,
-                        TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV), results);
-    }
-
-    public void testStringToContentRatings_twoInOrder() {
-        TvContentRating[] results = TvContentRatingCache.stringToContentRatings(MA_AND_Y7);
-        MoreAsserts.assertEquals("ratings",
-                asArray(TvContentRatingConstants.CONTENT_RATING_US_TV_MA,
-                        TvContentRatingConstants.CONTENT_RATING_US_TV_Y7_US_TV_FV), results);
-    }
-
-    public void testStringToContentRatings_double() {
-        TvContentRating[] results = TvContentRatingCache.stringToContentRatings(
-                TvContentRatingConstants.STRING_US_TV_MA + ","
-                        + TvContentRatingConstants.STRING_US_TV_MA);
-        MoreAsserts
-                .assertEquals("ratings", asArray(TvContentRatingConstants.CONTENT_RATING_US_TV_MA),
-                        results);
-    }
-
-    private static TvContentRating[] asArray(TvContentRating... ratings) {
-        return ratings;
-    }
-}
diff --git a/tests/unit/src/com/android/tv/data/ChannelDataManagerTest.java b/tests/unit/src/com/android/tv/data/ChannelDataManagerTest.java
index 9f9ada1..7a4a498 100644
--- a/tests/unit/src/com/android/tv/data/ChannelDataManagerTest.java
+++ b/tests/unit/src/com/android/tv/data/ChannelDataManagerTest.java
@@ -16,6 +16,12 @@
 
 package com.android.tv.data;
 
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.content.ContentProvider;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -26,9 +32,7 @@
 import android.media.tv.TvContract.Channels;
 import android.net.Uri;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
-import android.test.UiThreadTest;
 import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockCursor;
@@ -38,9 +42,11 @@
 
 import com.android.tv.testing.ChannelInfo;
 import com.android.tv.testing.Constants;
-import com.android.tv.testing.Utils;
 import com.android.tv.util.TvInputManagerHelper;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Matchers;
 import org.mockito.Mockito;
 
@@ -57,14 +63,13 @@
  * Note that all the methods of {@link ChannelDataManager} should be called from the UI thread.
  */
 @SmallTest
-public class ChannelDataManagerTest extends AndroidTestCase {
+public class ChannelDataManagerTest {
     private static final boolean DEBUG = false;
     private static final String TAG = "ChannelDataManagerTest";
 
     // Wait time for expected success.
     private static final long WAIT_TIME_OUT_MS = 1000L;
     private static final String DUMMY_INPUT_ID = "dummy";
-    // TODO: Use Channels.COLUMN_BROWSABLE and Channels.COLUMN_LOCKED instead.
     private static final String COLUMN_BROWSABLE = "browsable";
     private static final String COLUMN_LOCKED = "locked";
 
@@ -73,51 +78,59 @@
     private FakeContentResolver mContentResolver;
     private FakeContentProvider mContentProvider;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         assertTrue("More than 2 channels to test", Constants.UNIT_TEST_CHANNEL_COUNT > 2);
 
-        mContentProvider = new FakeContentProvider(getContext());
+        mContentProvider = new FakeContentProvider(getTargetContext());
         mContentResolver = new FakeContentResolver();
         mContentResolver.addProvider(TvContract.AUTHORITY, mContentProvider);
         mListener = new TestChannelDataManagerListener();
-        Utils.runOnMainSync(new Runnable() {
+        getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
                 TvInputManagerHelper mockHelper = Mockito.mock(TvInputManagerHelper.class);
                 Mockito.when(mockHelper.hasTvInputInfo(Matchers.anyString())).thenReturn(true);
-                mChannelDataManager = new ChannelDataManager(getContext(), mockHelper,
+                mChannelDataManager = new ChannelDataManager(getTargetContext(), mockHelper,
                         mContentResolver);
                 mChannelDataManager.addListener(mListener);
             }
         });
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        Utils.runOnMainSync(new Runnable() {
+    @After
+    public void tearDown() {
+        getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
                 mChannelDataManager.stop();
             }
         });
-        super.tearDown();
     }
 
-    private void startAndWaitForComplete() throws Exception {
-        mChannelDataManager.start();
+    private void startAndWaitForComplete() throws InterruptedException {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mChannelDataManager.start();
+            }
+        });
         assertTrue(mListener.loadFinishedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
     }
 
-    private void restart() throws Exception {
-        mChannelDataManager.stop();
-        mListener.reset();
+    private void restart() throws InterruptedException {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mChannelDataManager.stop();
+                mListener.reset();
+            }
+        });
         startAndWaitForComplete();
     }
 
-    @UiThreadTest
-    public void testIsDbLoadFinished() throws Exception {
+    @Test
+    public void testIsDbLoadFinished() throws InterruptedException {
         startAndWaitForComplete();
         assertTrue(mChannelDataManager.isDbLoadFinished());
     }
@@ -128,8 +141,8 @@
      *   - {@link ChannelDataManager#getChannelList}
      *   - {@link ChannelDataManager#getChannel}
      */
-    @UiThreadTest
-    public void testGetChannels() throws Exception {
+    @Test
+    public void testGetChannels() throws InterruptedException {
         startAndWaitForComplete();
 
         // Test {@link ChannelDataManager#getChannelCount}
@@ -138,7 +151,7 @@
         // Test {@link ChannelDataManager#getChannelList}
         List<ChannelInfo> channelInfoList = new ArrayList<>();
         for (int i = 1; i <= Constants.UNIT_TEST_CHANNEL_COUNT; i++) {
-            channelInfoList.add(ChannelInfo.create(getContext(), i));
+            channelInfoList.add(ChannelInfo.create(getTargetContext(), i));
         }
         List<Channel> channelList = mChannelDataManager.getChannelList();
         for (Channel channel : channelList) {
@@ -163,8 +176,8 @@
     /**
      * Test for {@link ChannelDataManager#getChannelCount} when no channel is available.
      */
-    @UiThreadTest
-    public void testGetChannels_noChannels() throws Exception {
+    @Test
+    public void testGetChannels_noChannels() throws InterruptedException {
         mContentProvider.clear();
         startAndWaitForComplete();
         assertEquals(0, mChannelDataManager.getChannelCount());
@@ -175,12 +188,12 @@
      *   - {@link ChannelDataManager#updateBrowsable}
      *   - {@link ChannelDataManager#applyUpdatedValuesToDb}
      */
-    @UiThreadTest
-    public void testBrowsable() throws Exception {
+    @Test
+    public void testBrowsable() throws InterruptedException {
         startAndWaitForComplete();
 
         // Test if all channels are browsable
-        List<Channel> channelList = new ArrayList<>(mChannelDataManager.getChannelList());
+        List<Channel> channelList = mChannelDataManager.getChannelList();
         List<Channel> browsableChannelList = mChannelDataManager.getBrowsableChannelList();
         for (Channel browsableChannel : browsableChannelList) {
             boolean found = channelList.remove(browsableChannel);
@@ -189,9 +202,10 @@
         assertEquals(0, channelList.size());
 
         // Prepare for next tests.
+        channelList = mChannelDataManager.getChannelList();
         TestChannelDataManagerChannelListener channelListener =
                 new TestChannelDataManagerChannelListener();
-        Channel channel1 = mChannelDataManager.getChannelList().get(0);
+        Channel channel1 = channelList.get(0);
         mChannelDataManager.addChannelListener(channel1.getId(), channelListener);
 
         // Test {@link ChannelDataManager#updateBrowsable} & notification.
@@ -216,15 +230,16 @@
      *   - {@link ChannelDataManager#updateBrowsable}
      *   - {@link ChannelDataManager#applyUpdatedValuesToDb}
      */
-    @UiThreadTest
-    public void testBrowsable_skipNotification() throws Exception {
+    @Test
+    public void testBrowsable_skipNotification() throws InterruptedException {
         startAndWaitForComplete();
 
+        List<Channel> channels = mChannelDataManager.getChannelList();
         // Prepare for next tests.
         TestChannelDataManagerChannelListener channelListener =
                 new TestChannelDataManagerChannelListener();
-        Channel channel1 = mChannelDataManager.getChannelList().get(0);
-        Channel channel2 = mChannelDataManager.getChannelList().get(1);
+        Channel channel1 = channels.get(0);
+        Channel channel2 = channels.get(1);
         mChannelDataManager.addChannelListener(channel1.getId(), channelListener);
         mChannelDataManager.addChannelListener(channel2.getId(), channelListener);
 
@@ -252,8 +267,8 @@
      *   - {@link ChannelDataManager#updateLocked}
      *   - {@link ChannelDataManager#applyUpdatedValuesToDb}
      */
-    @UiThreadTest
-    public void testLocked() throws Exception {
+    @Test
+    public void testLocked() throws InterruptedException {
         startAndWaitForComplete();
 
         // Test if all channels aren't locked at the first time.
@@ -283,14 +298,14 @@
     /**
      * Test ChannelDataManager when channels in TvContract are updated, removed, or added.
      */
-    @UiThreadTest
-    public void testChannelListChanged() throws Exception {
+    @Test
+    public void testChannelListChanged() throws InterruptedException {
         startAndWaitForComplete();
 
         // Test channel add.
         mListener.reset();
         long testChannelId = Constants.UNIT_TEST_CHANNEL_COUNT + 1;
-        ChannelInfo testChannelInfo = ChannelInfo.create(getContext(), (int) testChannelId);
+        ChannelInfo testChannelInfo = ChannelInfo.create(getTargetContext(), (int) testChannelId);
         testChannelId = Constants.UNIT_TEST_CHANNEL_COUNT + 1;
         mContentProvider.simulateInsert(testChannelInfo);
         assertTrue(
@@ -376,7 +391,7 @@
             super(context);
             for (int i = 1; i <= Constants.UNIT_TEST_CHANNEL_COUNT; i++) {
                 mChannelInfoList.put(i,
-                        new ChannelInfoWrapper(ChannelInfo.create(getContext(), i)));
+                        new ChannelInfoWrapper(ChannelInfo.create(getTargetContext(), i)));
             }
         }
 
@@ -466,8 +481,8 @@
          */
         public void simulateInsert(ChannelInfo testChannelInfo) {
             long channelId = testChannelInfo.originalNetworkId;
-            mChannelInfoList.put((int) channelId,
-                    new ChannelInfoWrapper(ChannelInfo.create(getContext(), (int) channelId)));
+            mChannelInfoList.put((int) channelId, new ChannelInfoWrapper(
+                    ChannelInfo.create(getTargetContext(), (int) channelId)));
             mContentResolver.notifyChange(TvContract.buildChannelUri(channelId), null);
         }
 
diff --git a/tests/unit/src/com/android/tv/data/ChannelNumberTest.java b/tests/unit/src/com/android/tv/data/ChannelNumberTest.java
index 4e6e9f3..827dcdb 100644
--- a/tests/unit/src/com/android/tv/data/ChannelNumberTest.java
+++ b/tests/unit/src/com/android/tv/data/ChannelNumberTest.java
@@ -16,22 +16,24 @@
 package com.android.tv.data;
 
 import static com.android.tv.data.ChannelNumber.parseChannelNumber;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 
 import android.support.test.filters.SmallTest;
 
 import com.android.tv.testing.ComparableTester;
 
-import junit.framework.TestCase;
+import org.junit.Test;
 
 /**
  * Tests for {@link ChannelNumber}.
  */
 @SmallTest
-public class ChannelNumberTest extends TestCase {
-
+public class ChannelNumberTest {
     /**
      * Test method for {@link ChannelNumber#ChannelNumber()}.
      */
+    @Test
     public void testChannelNumber() {
         assertChannelEquals(new ChannelNumber(), "", false, "");
     }
@@ -40,32 +42,32 @@
      * Test method for
      * {@link com.android.tv.data.ChannelNumber#parseChannelNumber(java.lang.String)}.
      */
+    @Test
     public void testParseChannelNumber() {
         assertNull(parseChannelNumber(""));
-        assertNull(parseChannelNumber(" "));
+        assertNull(parseChannelNumber("-"));
         assertNull(parseChannelNumber("abcd12"));
         assertNull(parseChannelNumber("12abcd"));
         assertNull(parseChannelNumber("-12"));
         assertChannelEquals(parseChannelNumber("1"), "1", false, "");
-        assertChannelEquals(parseChannelNumber("1234 4321"), "1234", true, "4321");
+        assertChannelEquals(parseChannelNumber("1234-4321"), "1234", true, "4321");
         assertChannelEquals(parseChannelNumber("3-4"), "3", true, "4");
-        assertChannelEquals(parseChannelNumber("5.6"), "5", true, "6");
+        assertChannelEquals(parseChannelNumber("5-6"), "5", true, "6");
     }
 
     /**
      * Test method for {@link ChannelNumber#compareTo(com.android.tv.data.ChannelNumber)}.
      */
+    @Test
     public void testCompareTo() {
         new ComparableTester<ChannelNumber>()
                 .addEquivalentGroup(parseChannelNumber("1"), parseChannelNumber("1"))
                 .addEquivalentGroup(parseChannelNumber("2"))
-                .addEquivalentGroup(parseChannelNumber("2 1"), parseChannelNumber("2.1"),
-                        parseChannelNumber("2-1"))
+                .addEquivalentGroup(parseChannelNumber("2-1"))
                 .addEquivalentGroup(parseChannelNumber("2-2"))
                 .addEquivalentGroup(parseChannelNumber("2-10"))
                 .addEquivalentGroup(parseChannelNumber("3"))
-                .addEquivalentGroup(parseChannelNumber("4"), parseChannelNumber("4 0"),
-                        parseChannelNumber("4.0"), parseChannelNumber("4-0"))
+                .addEquivalentGroup(parseChannelNumber("4"), parseChannelNumber("4-0"))
                 .addEquivalentGroup(parseChannelNumber("10"))
                 .addEquivalentGroup(parseChannelNumber("100"))
                 .test();
@@ -74,6 +76,7 @@
     /**
      * Test method for {@link ChannelNumber#compare(java.lang.String, java.lang.String)}.
      */
+    @Test
     public void testCompare() {
         // Only need to test nulls, the reset is tested by testCompareTo
         assertEquals("compareTo(null,null)", 0, ChannelNumber.compare(null, null));
diff --git a/tests/unit/src/com/android/tv/data/ChannelTest.java b/tests/unit/src/com/android/tv/data/ChannelTest.java
index 95e3ee9..d270e27 100644
--- a/tests/unit/src/com/android/tv/data/ChannelTest.java
+++ b/tests/unit/src/com/android/tv/data/ChannelTest.java
@@ -16,17 +16,21 @@
 
 package com.android.tv.data;
 
+import static org.junit.Assert.assertEquals;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 
 import com.android.tv.testing.ComparatorTester;
 import com.android.tv.util.TvInputManagerHelper;
 
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Matchers;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
@@ -38,7 +42,7 @@
  * Tests for {@link Channel}.
  */
 @SmallTest
-public class ChannelTest extends AndroidTestCase {
+public class ChannelTest {
     // Used for testing TV inputs with invalid input package. This could happen when a TV input is
     // uninstalled while drawing an app link card.
     private static final String INVALID_TV_INPUT_PACKAGE_NAME =
@@ -59,9 +63,8 @@
     private Intent mInvalidIntent;
     private Intent mValidIntent;
 
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws NameNotFoundException {
         mInvalidIntent = new Intent(Intent.ACTION_VIEW);
         mInvalidIntent.setComponent(new ComponentName(INVALID_TV_INPUT_PACKAGE_NAME, ".test"));
         mValidIntent = new Intent(Intent.ACTION_VIEW);
@@ -103,6 +106,7 @@
         Mockito.when(mMockContext.getPackageManager()).thenReturn(mockPackageManager);
     }
 
+    @Test
     public void testGetAppLinkType_NoText_NoIntent() {
         assertAppLinkType(Channel.APP_LINK_TYPE_NONE, INVALID_TV_INPUT_PACKAGE_NAME, null, null);
         assertAppLinkType(Channel.APP_LINK_TYPE_NONE, LIVE_CHANNELS_PACKAGE_NAME, null, null);
@@ -226,7 +230,6 @@
      * See <a href="http://b/23031603">b/23031603</a>.
      */
     public void testComparatorLabel() {
-
         TvInputManagerHelper manager = Mockito.mock(TvInputManagerHelper.class);
         Mockito.when(manager.isPartnerInput(Matchers.anyString())).thenAnswer(
                 new Answer<Boolean>() {
@@ -254,6 +257,29 @@
         comparatorTester.test();
     }
 
+    public void testNormalizeChannelNumber() {
+        assertNormalizedDisplayNumber(null, null);
+        assertNormalizedDisplayNumber("", "");
+        assertNormalizedDisplayNumber("1", "1");
+        assertNormalizedDisplayNumber("abcde", "abcde");
+        assertNormalizedDisplayNumber("1-1", "1-1");
+        assertNormalizedDisplayNumber("1.1", "1-1");
+        assertNormalizedDisplayNumber("1 1", "1-1");
+        assertNormalizedDisplayNumber("1\u058a1", "1-1");
+        assertNormalizedDisplayNumber("1\u05be1", "1-1");
+        assertNormalizedDisplayNumber("1\u14001", "1-1");
+        assertNormalizedDisplayNumber("1\u18061", "1-1");
+        assertNormalizedDisplayNumber("1\u20101", "1-1");
+        assertNormalizedDisplayNumber("1\u20111", "1-1");
+        assertNormalizedDisplayNumber("1\u20121", "1-1");
+        assertNormalizedDisplayNumber("1\u20131", "1-1");
+        assertNormalizedDisplayNumber("1\u20141", "1-1");
+    }
+
+    private void assertNormalizedDisplayNumber(String displayNumber, String normalized) {
+        assertEquals(normalized, Channel.normalizeDisplayNumber(displayNumber));
+    }
+
     private class TestChannelComparator extends Channel.DefaultComparator {
         public TestChannelComparator(TvInputManagerHelper manager) {
             super(null, manager);
diff --git a/tests/unit/src/com/android/tv/data/GenreItemTest.java b/tests/unit/src/com/android/tv/data/GenreItemTest.java
index fb48fd4..fdbcb59 100644
--- a/tests/unit/src/com/android/tv/data/GenreItemTest.java
+++ b/tests/unit/src/com/android/tv/data/GenreItemTest.java
@@ -16,23 +16,32 @@
 
 package com.android.tv.data;
 
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import android.media.tv.TvContract.Programs.Genres;
 import android.os.Build;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
+
+import org.junit.Test;
 
 /**
  * Tests for {@link Channel}.
  */
 @SmallTest
-public class GenreItemTest extends AndroidTestCase {
+public class GenreItemTest {
     private static final String INVALID_GENRE = "INVALID GENRE";
 
+    @Test
     public void testGetLabels() {
         // Checks if no exception is thrown.
-        GenreItems.getLabels(getContext());
+        GenreItems.getLabels(getTargetContext());
     }
 
+    @Test
     public void testGetCanonicalGenre() {
         int count = GenreItems.getGenreCount();
         assertNull(GenreItems.getCanonicalGenre(GenreItems.ID_ALL_CHANNELS));
@@ -41,6 +50,7 @@
         }
     }
 
+    @Test
     public void testGetId_base() {
         int count = GenreItems.getGenreCount();
         assertEquals(GenreItems.ID_ALL_CHANNELS, GenreItems.getId(null));
@@ -58,6 +68,7 @@
         assertInRange(GenreItems.getId(Genres.GAMING), 1, count - 1);
     }
 
+    @Test
     public void testGetId_lmp_mr1() {
         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP_MR1) {
             assertEquals(GenreItems.ID_ALL_CHANNELS, GenreItems.getId(Genres.ARTS));
diff --git a/tests/unit/src/com/android/tv/data/ProgramDataManagerTest.java b/tests/unit/src/com/android/tv/data/ProgramDataManagerTest.java
index 430eef9..5457051 100644
--- a/tests/unit/src/com/android/tv/data/ProgramDataManagerTest.java
+++ b/tests/unit/src/com/android/tv/data/ProgramDataManagerTest.java
@@ -16,14 +16,20 @@
 
 package com.android.tv.data;
 
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import android.content.Context;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.media.tv.TvContract;
 import android.net.Uri;
 import android.os.HandlerThread;
+import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 import android.test.mock.MockContentProvider;
 import android.test.mock.MockContentResolver;
 import android.test.mock.MockCursor;
@@ -35,6 +41,10 @@
 import com.android.tv.testing.ProgramInfo;
 import com.android.tv.util.Utils;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -45,7 +55,7 @@
  * Test for {@link com.android.tv.data.ProgramDataManager}
  */
 @SmallTest
-public class ProgramDataManagerTest extends AndroidTestCase {
+public class ProgramDataManagerTest {
     private static final boolean DEBUG = false;
     private static final String TAG = "ProgramDataManagerTest";
 
@@ -66,31 +76,28 @@
     private FakeContentResolver mContentResolver;
     private FakeContentProvider mContentProvider;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
+    @Before
+    public void setUp() {
         mClock = FakeClock.createWithCurrentTime();
         mListener = new TestProgramDataManagerListener();
-        mContentProvider = new FakeContentProvider(getContext());
+        mContentProvider = new FakeContentProvider(getTargetContext());
         mContentResolver = new FakeContentResolver();
         mContentResolver.addProvider(TvContract.AUTHORITY, mContentProvider);
         mHandlerThread = new HandlerThread(TAG);
         mHandlerThread.start();
         mProgramDataManager = new ProgramDataManager(
-                mContentResolver, mClock, mHandlerThread.getLooper(), null);
+                mContentResolver, mClock, mHandlerThread.getLooper());
         mProgramDataManager.setPrefetchEnabled(true);
         mProgramDataManager.addListener(mListener);
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @After
+    public void tearDown() {
         mHandlerThread.quitSafely();
         mProgramDataManager.stop();
     }
 
-    private void startAndWaitForComplete() throws Exception {
+    private void startAndWaitForComplete() throws InterruptedException {
         mProgramDataManager.start();
         assertTrue(mListener.programUpdatedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
     }
@@ -98,12 +105,13 @@
     /**
      * Test for {@link ProgramInfo#getIndex} and {@link ProgramInfo#getStartTimeMs}.
      */
+    @Test
     public void testProgramUtils() {
         ProgramInfo stub = ProgramInfo.create();
         for (long channelId = 1; channelId < Constants.UNIT_TEST_CHANNEL_COUNT; channelId++) {
             int index = stub.getIndex(mClock.currentTimeMillis(), channelId);
             long startTimeMs = stub.getStartTimeMs(index, channelId);
-            ProgramInfo programAt = stub.build(getContext(), index);
+            ProgramInfo programAt = stub.build(InstrumentationRegistry.getContext(), index);
             assertTrue(startTimeMs <= mClock.currentTimeMillis());
             assertTrue(mClock.currentTimeMillis() < startTimeMs + programAt.durationMs);
         }
@@ -118,7 +126,8 @@
      * {@link ProgramDataManager#setPrefetchTimeRange(long)}.
      * </p>
      */
-    public void testGetPrograms() throws Exception {
+    @Test
+    public void testGetPrograms() throws InterruptedException {
         // Initial setup to test {@link ProgramDataManager#setPrefetchTimeRange(long)}.
         long preventSnapDelayMs = ProgramDataManager.PROGRAM_GUIDE_SNAP_TIME_MS * 2;
         long prefetchTimeRangeStartMs = System.currentTimeMillis() + preventSnapDelayMs;
@@ -140,7 +149,7 @@
             ProgramInfo stub = ProgramInfo.create();
             int index = stub.getIndex(mClock.currentTimeMillis(), channelId);
             for (Program program : programs) {
-                ProgramInfo programInfoAt = stub.build(getContext(), index);
+                ProgramInfo programInfoAt = stub.build(InstrumentationRegistry.getContext(), index);
                 long startTimeMs = stub.getStartTimeMs(index, channelId);
                 assertProgramEquals(startTimeMs, programInfoAt, program);
                 index++;
@@ -167,14 +176,15 @@
      * {@link ProgramDataManager#removeOnCurrentProgramUpdatedListener}.
      * </p>
      */
-    public void testCurrentProgramListener() throws Exception {
+    @Test
+    public void testCurrentProgramListener() throws InterruptedException {
         final long testChannelId = 1;
         ProgramInfo stub = ProgramInfo.create();
         int index = stub.getIndex(mClock.currentTimeMillis(), testChannelId);
         // Set current time to few seconds before the current program ends,
         // so we can see if callback is called as expected.
         long nextProgramStartTimeMs = stub.getStartTimeMs(index + 1, testChannelId);
-        ProgramInfo nextProgramInfo = stub.build(getContext(), index + 1);
+        ProgramInfo nextProgramInfo = stub.build(InstrumentationRegistry.getContext(), index + 1);
         mClock.setCurrentTimeMillis(nextProgramStartTimeMs - (WAIT_TIME_OUT_MS / 2));
 
         startAndWaitForComplete();
@@ -196,7 +206,8 @@
     /**
      * Test if program data is refreshed after the program insertion.
      */
-    public void testContentProviderUpdate() throws Exception {
+    @Test
+    public void testContentProviderUpdate() throws InterruptedException {
         final long testChannelId = 1;
         startAndWaitForComplete();
         // Force program data manager to update program data whenever it's changes.
@@ -217,7 +228,8 @@
     /**
      * Test for {@link ProgramDataManager#setPauseProgramUpdate(boolean)}.
      */
-    public void testSetPauseProgramUpdate() throws Exception {
+    @Test
+    public void testSetPauseProgramUpdate() throws InterruptedException {
         final long testChannelId = 1;
         startAndWaitForComplete();
         // Force program data manager to update program data whenever it's changes.
@@ -290,7 +302,7 @@
                 int index = stub.getIndex(startTimeMs, i);
                 long programStartTimeMs = stub.getStartTimeMs(index, i);
                 while (programStartTimeMs < endTimeMs) {
-                    ProgramInfo programAt = stub.build(getContext(), index);
+                    ProgramInfo programAt = stub.build(InstrumentationRegistry.getContext(), index);
                     programInfoList.add(
                             new ProgramInfoWrapper(index, programStartTimeMs, programAt));
                     index++;
@@ -340,7 +352,8 @@
             ProgramInfo stub = ProgramInfo.create();
             ProgramInfoWrapper last = programList.get(programList.size() - 1);
             while (last.startTimeMs < endTimeMs) {
-                ProgramInfo nextProgramInfo = stub.build(getContext(), last.index + 1);
+                ProgramInfo nextProgramInfo = stub.build(InstrumentationRegistry.getContext(),
+                        last.index + 1);
                 ProgramInfoWrapper next = new ProgramInfoWrapper(last.index + 1,
                         last.startTimeMs + last.programInfo.durationMs, nextProgramInfo);
                 programList.add(next);
diff --git a/tests/unit/src/com/android/tv/data/ProgramTest.java b/tests/unit/src/com/android/tv/data/ProgramTest.java
index 7e474cd..1d1f6c1 100644
--- a/tests/unit/src/com/android/tv/data/ProgramTest.java
+++ b/tests/unit/src/com/android/tv/data/ProgramTest.java
@@ -17,17 +17,18 @@
 
 import static android.media.tv.TvContract.Programs.Genres.COMEDY;
 import static android.media.tv.TvContract.Programs.Genres.FAMILY_KIDS;
-
-import com.android.tv.data.Program.CriticScore;
-import com.android.tv.dvr.SeriesRecording;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import android.media.tv.TvContentRating;
 import android.media.tv.TvContract.Programs.Genres;
 import android.os.Parcel;
 import android.support.test.filters.SmallTest;
-import android.util.Log;
 
-import junit.framework.TestCase;
+import com.android.tv.data.Program.CriticScore;
+
+import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -37,19 +38,20 @@
  * Tests for {@link Program}.
  */
 @SmallTest
-public class ProgramTest extends TestCase {
-
+public class ProgramTest {
     private static final int NOT_FOUND_GENRE = 987;
 
     private static final int FAMILY_GENRE_ID = GenreItems.getId(FAMILY_KIDS);
 
     private static final int COMEDY_GENRE_ID = GenreItems.getId(COMEDY);
 
+    @Test
     public void testBuild() {
         Program program = new Program.Builder().build();
         assertEquals("isValid", false, program.isValid());
     }
 
+    @Test
     public void testNoGenres() {
         Program program = new Program.Builder()
                 .setCanonicalGenres("")
@@ -61,6 +63,7 @@
         assertHasGenre(program, GenreItems.ID_ALL_CHANNELS, true);
     }
 
+    @Test
     public void testFamilyGenre() {
         Program program = new Program.Builder()
                 .setCanonicalGenres(FAMILY_KIDS)
@@ -72,6 +75,7 @@
         assertHasGenre(program, GenreItems.ID_ALL_CHANNELS, true);
     }
 
+    @Test
     public void testFamilyComedyGenre() {
         Program program = new Program.Builder()
                 .setCanonicalGenres(FAMILY_KIDS + ", " + COMEDY)
@@ -83,6 +87,7 @@
         assertHasGenre(program, GenreItems.ID_ALL_CHANNELS, true);
     }
 
+    @Test
     public void testOtherGenre() {
         Program program = new Program.Builder()
                 .setCanonicalGenres("other")
@@ -94,7 +99,8 @@
         assertHasGenre(program, GenreItems.ID_ALL_CHANNELS, true);
     }
 
-    public void testParcelable() throws Exception {
+    @Test
+    public void testParcelable() {
         List<CriticScore> criticScores = new ArrayList<>();
         criticScores.add(new CriticScore("1", "2", "3"));
         criticScores.add(new CriticScore("4", "5", "6"));
@@ -139,6 +145,7 @@
         }
     }
 
+    @Test
     public void testParcelableWithCriticScore() {
         Program program = new Program.Builder()
                 .setTitle("MyTitle")
diff --git a/tests/unit/src/com/android/tv/data/TvInputNewComparatorTest.java b/tests/unit/src/com/android/tv/data/TvInputNewComparatorTest.java
index f5504d4..b4682dd 100644
--- a/tests/unit/src/com/android/tv/data/TvInputNewComparatorTest.java
+++ b/tests/unit/src/com/android/tv/data/TvInputNewComparatorTest.java
@@ -19,8 +19,6 @@
 import android.content.pm.ResolveInfo;
 import android.media.tv.TvInputInfo;
 import android.support.test.filters.SmallTest;
-import android.support.test.filters.Suppress;
-import android.test.AndroidTestCase;
 import android.util.Pair;
 
 import com.android.tv.testing.ComparatorTester;
@@ -28,6 +26,7 @@
 import com.android.tv.util.TestUtils;
 import com.android.tv.util.TvInputManagerHelper;
 
+import org.junit.Test;
 import org.mockito.Matchers;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
@@ -40,16 +39,16 @@
  * Test for {@link TvInputNewComparator}
  */
 @SmallTest
-public class TvInputNewComparatorTest extends AndroidTestCase {
+public class TvInputNewComparatorTest {
+    @Test
     public void testComparator() throws Exception {
-        final LinkedHashMap<String, Pair<Boolean, Boolean>> INPUT_ID_TO_NEW_INPUT =
-                new LinkedHashMap<>();
-        INPUT_ID_TO_NEW_INPUT.put("2_new_input", new Pair(true, false));
-        INPUT_ID_TO_NEW_INPUT.put("4_new_input", new Pair(true, false));
-        INPUT_ID_TO_NEW_INPUT.put("4_old_input", new Pair(false, false));
-        INPUT_ID_TO_NEW_INPUT.put("0_old_input", new Pair(false, true));
-        INPUT_ID_TO_NEW_INPUT.put("1_old_input", new Pair(false, true));
-        INPUT_ID_TO_NEW_INPUT.put("3_old_input", new Pair(false, true));
+        LinkedHashMap<String, Pair<Boolean, Boolean>> inputIdToNewInput = new LinkedHashMap<>();
+        inputIdToNewInput.put("2_new_input", new Pair<>(true, false));
+        inputIdToNewInput.put("4_new_input", new Pair<>(true, false));
+        inputIdToNewInput.put("4_old_input", new Pair<>(false, false));
+        inputIdToNewInput.put("0_old_input", new Pair<>(false, true));
+        inputIdToNewInput.put("1_old_input", new Pair<>(false, true));
+        inputIdToNewInput.put("3_old_input", new Pair<>(false, true));
 
         SetupUtils setupUtils = Mockito.mock(SetupUtils.class);
         Mockito.when(setupUtils.isNewInput(Matchers.anyString())).thenAnswer(
@@ -57,7 +56,7 @@
                     @Override
                     public Boolean answer(InvocationOnMock invocation) throws Throwable {
                         String inputId = (String) invocation.getArguments()[0];
-                        return INPUT_ID_TO_NEW_INPUT.get(inputId).first;
+                        return inputIdToNewInput.get(inputId).first;
                     }
                 }
         );
@@ -66,7 +65,7 @@
                     @Override
                     public Boolean answer(InvocationOnMock invocation) throws Throwable {
                         String inputId = (String) invocation.getArguments()[0];
-                        return INPUT_ID_TO_NEW_INPUT.get(inputId).second;
+                        return inputIdToNewInput.get(inputId).second;
                     }
                 }
         );
@@ -83,7 +82,7 @@
         ComparatorTester<TvInputInfo> comparatorTester =
                 ComparatorTester.withoutEqualsTest(comparator);
         ResolveInfo resolveInfo = TestUtils.createResolveInfo("test", "test");
-        for (String id : INPUT_ID_TO_NEW_INPUT.keySet()) {
+        for (String id : inputIdToNewInput.keySet()) {
             // Put mock resolveInfo to prevent NPE in {@link TvInputInfo#toString}
             TvInputInfo info1 = TestUtils.createTvInputInfo(
                     resolveInfo, id, "test1", TvInputInfo.TYPE_TUNER, false);
diff --git a/tests/unit/src/com/android/tv/data/WatchedHistoryManagerTest.java b/tests/unit/src/com/android/tv/data/WatchedHistoryManagerTest.java
index c86bb72..7eea1be 100644
--- a/tests/unit/src/com/android/tv/data/WatchedHistoryManagerTest.java
+++ b/tests/unit/src/com/android/tv/data/WatchedHistoryManagerTest.java
@@ -16,60 +16,57 @@
 
 package com.android.tv.data;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.filters.Suppress;
-import android.test.AndroidTestCase;
-import android.test.UiThreadTest;
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Looper;
+import android.support.test.filters.MediumTest;
 
 import com.android.tv.data.WatchedHistoryManager.WatchedRecord;
-import com.android.tv.testing.Utils;
 
-import java.util.concurrent.CountDownLatch;
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.concurrent.TimeUnit;
 
 /**
  * Test for {@link com.android.tv.data.WatchedHistoryManagerTest}
+ * <p>
+ * This is a medium test because it load files which accessing SharedPreferences.
  */
-@SmallTest
-@Suppress // http://b/27156462
-public class WatchedHistoryManagerTest extends AndroidTestCase {
-    private static final boolean DEBUG = false;
-    private static final String TAG = "WatchedHistoryManager";
-
+@MediumTest
+public class WatchedHistoryManagerTest {
     // Wait time for expected success.
-    private static final long WAIT_TIME_OUT_MS = 1000L;
     private static final int MAX_HISTORY_SIZE = 100;
 
     private WatchedHistoryManager mWatchedHistoryManager;
     private TestWatchedHistoryManagerListener mListener;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        Utils.runOnMainSync(new Runnable() {
-            @Override
-            public void run() {
-                mWatchedHistoryManager = new WatchedHistoryManager(getContext(), MAX_HISTORY_SIZE);
-                mListener = new TestWatchedHistoryManagerListener();
-                mWatchedHistoryManager.setListener(mListener);
-            }
-        });
+    @Before
+    public void setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+        mWatchedHistoryManager = new WatchedHistoryManager(getTargetContext(), MAX_HISTORY_SIZE);
+        mListener = new TestWatchedHistoryManagerListener();
+        mWatchedHistoryManager.setListener(mListener);
     }
 
-    private void startAndWaitForComplete() throws Exception {
+    private void startAndWaitForComplete() throws InterruptedException {
         mWatchedHistoryManager.start();
-        assertTrue(mListener.loadFinishedLatch.await(WAIT_TIME_OUT_MS, TimeUnit.MILLISECONDS));
+        assertTrue(mListener.mLoadFinished);
     }
 
-    @UiThreadTest
-    public void testIsLoaded() throws Exception {
-        assertFalse(mWatchedHistoryManager.isLoaded());
+    @Test
+    public void testIsLoaded() throws InterruptedException {
         startAndWaitForComplete();
         assertTrue(mWatchedHistoryManager.isLoaded());
     }
 
-    @UiThreadTest
-    public void testLogChannelViewStop() throws Exception {
+    @Test
+    public void testLogChannelViewStop() throws InterruptedException {
         startAndWaitForComplete();
         long fakeId = 100000000;
         long time = System.currentTimeMillis();
@@ -86,8 +83,8 @@
         assertEquals(record, recordFromSharedPreferences);
     }
 
-    @UiThreadTest
-    public void testCircularHistoryQueue() throws Exception {
+    @Test
+    public void testCircularHistoryQueue() throws InterruptedException {
         startAndWaitForComplete();
         final long startChannelId = 100000000;
         long time = System.currentTimeMillis();
@@ -111,7 +108,7 @@
                 mWatchedHistoryManager.getRecordFromSharedPreferences(MAX_HISTORY_SIZE));
     }
 
-    @UiThreadTest
+    @Test
     public void testWatchedRecordEquals() {
         assertTrue(new WatchedRecord(1, 2, 3).equals(new WatchedRecord(1, 2, 3)));
         assertFalse(new WatchedRecord(1, 2, 3).equals(new WatchedRecord(1, 2, 4)));
@@ -119,8 +116,8 @@
         assertFalse(new WatchedRecord(1, 2, 3).equals(new WatchedRecord(4, 2, 3)));
     }
 
-    @UiThreadTest
-    public void testEncodeDecodeWatchedRecord() throws Exception {
+    @Test
+    public void testEncodeDecodeWatchedRecord() {
         long fakeId = 100000000;
         long time = System.currentTimeMillis();
         long duration = TimeUnit.MINUTES.toMillis(10);
@@ -131,11 +128,11 @@
     }
 
     private class TestWatchedHistoryManagerListener implements WatchedHistoryManager.Listener {
-        public final CountDownLatch loadFinishedLatch = new CountDownLatch(1);
+        boolean mLoadFinished;
 
         @Override
         public void onLoadFinished() {
-            loadFinishedLatch.countDown();
+            mLoadFinished = true;
         }
 
         @Override
diff --git a/tests/unit/src/com/android/tv/dvr/BaseDvrDataManagerTest.java b/tests/unit/src/com/android/tv/dvr/BaseDvrDataManagerTest.java
index 1292759..5f0ae15 100644
--- a/tests/unit/src/com/android/tv/dvr/BaseDvrDataManagerTest.java
+++ b/tests/unit/src/com/android/tv/dvr/BaseDvrDataManagerTest.java
@@ -16,35 +16,51 @@
 
 package com.android.tv.dvr;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+
+import android.os.Build;
 import android.support.annotation.NonNull;
+import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 
+import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.feature.TestableFeature;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.testing.FakeClock;
 import com.android.tv.testing.dvr.RecordingTestUtils;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-/**
- * Tests for {@link BaseDvrDataManager} using {@link DvrDataManagerInMemoryImpl}.
- */
+/** Tests for {@link BaseDvrDataManager} using {@link DvrDataManagerInMemoryImpl}. */
 @SmallTest
-public class BaseDvrDataManagerTest extends AndroidTestCase {
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public class BaseDvrDataManagerTest {
     private static final String INPUT_ID = "input_id";
     private static final int CHANNEL_ID = 273;
 
+    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
     private DvrDataManagerInMemoryImpl mDvrDataManager;
     private FakeClock mFakeClock;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
+        mDvrFeature.enableForTest();
         mFakeClock = FakeClock.createWithCurrentTime();
         mDvrDataManager = new DvrDataManagerInMemoryImpl(getContext(), mFakeClock);
     }
 
+    @After
+    public void tearDown() {
+        mDvrFeature.resetForTests();
+    }
+
+    @Test
     public void testGetNonStartedScheduledRecordings() {
         ScheduledRecording recording = mDvrDataManager
                 .addScheduledRecordingInternal(createNewScheduledRecordingStartingNow());
@@ -52,6 +68,7 @@
         MoreAsserts.assertContentsInAnyOrder(result, recording);
     }
 
+    @Test
     public void testGetNonStartedScheduledRecordings_past() {
         mDvrDataManager.addScheduledRecordingInternal(createNewScheduledRecordingStartingNow());
         mFakeClock.increment(TimeUnit.MINUTES, 6);
diff --git a/tests/unit/src/com/android/tv/dvr/DvrDataManagerImplTest.java b/tests/unit/src/com/android/tv/dvr/DvrDataManagerImplTest.java
index b822f16..9771a2e 100644
--- a/tests/unit/src/com/android/tv/dvr/DvrDataManagerImplTest.java
+++ b/tests/unit/src/com/android/tv/dvr/DvrDataManagerImplTest.java
@@ -16,24 +16,29 @@
 
 package com.android.tv.dvr;
 
+import static org.junit.Assert.assertEquals;
+
+import android.os.Build;
+import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.testing.dvr.RecordingTestUtils;
 
-import junit.framework.TestCase;
+import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.List;
 
-/**
- * Tests for {@link DvrDataManagerImpl}
- */
+/** Tests for {@link DvrDataManagerImpl} */
 @SmallTest
-public class DvrDataManagerImplTest extends TestCase {
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public class DvrDataManagerImplTest {
     private static final String INPUT_ID = "input_id";
     private static final int CHANNEL_ID = 273;
 
-    public void testGetNextScheduledStartTimeAfter() throws Exception {
+    @Test
+    public void testGetNextScheduledStartTimeAfter() {
         long id = 1;
         List<ScheduledRecording> scheduledRecordings = new ArrayList<>();
         assertNextStartTime(scheduledRecordings, 0L, DvrDataManager.NEXT_START_TIME_NOT_FOUND);
diff --git a/tests/unit/src/com/android/tv/dvr/DvrDataManagerInMemoryImpl.java b/tests/unit/src/com/android/tv/dvr/DvrDataManagerInMemoryImpl.java
index 85e35c4..0a7ab46 100644
--- a/tests/unit/src/com/android/tv/dvr/DvrDataManagerInMemoryImpl.java
+++ b/tests/unit/src/com/android/tv/dvr/DvrDataManagerInMemoryImpl.java
@@ -17,14 +17,19 @@
 package com.android.tv.dvr;
 
 import android.content.Context;
+import android.os.Build;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
+import android.support.test.filters.SdkSuppress;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Range;
 
 import com.android.tv.common.SoftPreconditions;
-import com.android.tv.dvr.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.RecordedProgram;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.ScheduledRecording.RecordingState;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.util.Clock;
 
 import java.util.ArrayList;
@@ -34,10 +39,9 @@
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicLong;
 
-/**
- * A DVR Data manager that stores values in memory suitable for testing.
- */
-final class DvrDataManagerInMemoryImpl extends BaseDvrDataManager {
+/** A DVR Data manager that stores values in memory suitable for testing. */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public final class DvrDataManagerInMemoryImpl extends BaseDvrDataManager {
     private final static String TAG = "DvrDataManagerInMemory";
     private final AtomicLong mNextId = new AtomicLong(1);
     private final Map<Long, ScheduledRecording> mScheduledRecordings = new HashMap<>();
diff --git a/tests/unit/src/com/android/tv/dvr/DvrRecordingServiceTest.java b/tests/unit/src/com/android/tv/dvr/DvrRecordingServiceTest.java
deleted file mode 100644
index 0a203ed..0000000
--- a/tests/unit/src/com/android/tv/dvr/DvrRecordingServiceTest.java
+++ /dev/null
@@ -1,68 +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.dvr;
-
-import static org.mockito.Mockito.verify;
-
-import android.os.Build;
-import android.support.test.filters.SdkSuppress;
-import android.support.test.filters.SmallTest;
-import android.test.ServiceTestCase;
-
-import com.android.tv.common.feature.CommonFeatures;
-import com.android.tv.common.feature.TestableFeature;
-import com.android.tv.testing.FakeClock;
-
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for {@link DvrRecordingService}.
- */
-@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
-public class DvrRecordingServiceTest extends ServiceTestCase<DvrRecordingService> {
-    @Mock Scheduler mMockScheduler;
-    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
-    private final FakeClock mFakeClock = FakeClock.createWithCurrentTime();
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mDvrFeature.enableForTest();
-        MockitoAnnotations.initMocks(this);
-        setupService();
-        DvrRecordingService service = getService();
-        service.setScheduler(mMockScheduler);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mDvrFeature.resetForTests();
-        super.tearDown();
-    }
-
-    public DvrRecordingServiceTest() {
-        super(DvrRecordingService.class);
-    }
-
-    public void testStartService_null() throws Exception {
-        startService(null);
-        verify(mMockScheduler, Mockito.only()).update();
-    }
-}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/tv/dvr/DvrScheduleManagerTest.java b/tests/unit/src/com/android/tv/dvr/DvrScheduleManagerTest.java
index 2850a5f..1c77aa0 100644
--- a/tests/unit/src/com/android/tv/dvr/DvrScheduleManagerTest.java
+++ b/tests/unit/src/com/android/tv/dvr/DvrScheduleManagerTest.java
@@ -16,32 +16,39 @@
 
 package com.android.tv.dvr;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.os.Build;
+import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.test.MoreAsserts;
 import android.util.Range;
 
+import com.android.tv.dvr.DvrScheduleManager.ConflictInfo;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.testing.dvr.RecordingTestUtils;
 
-import junit.framework.TestCase;
+import org.junit.Test;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
-/**
- * Tests for {@link DvrScheduleManager}
- */
+/** Tests for {@link DvrScheduleManager} */
 @SmallTest
-public class DvrScheduleManagerTest extends TestCase {
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public class DvrScheduleManagerTest {
     private static final String INPUT_ID = "input_id";
 
+    @Test
     public void testGetConflictingSchedules_emptySchedule() {
         List<ScheduledRecording> schedules = new ArrayList<>();
         MoreAsserts.assertEmpty(DvrScheduleManager.getConflictingSchedules(schedules, 1));
     }
 
+    @Test
     public void testGetConflictingSchedules_noConflict() {
         long priority = 0;
         long channelId = 0;
@@ -68,6 +75,7 @@
         MoreAsserts.assertEmpty(DvrScheduleManager.getConflictingSchedules(schedules, 3));
     }
 
+    @Test
     public void testGetConflictingSchedules_noTuner() {
         long priority = 0;
         long channelId = 0;
@@ -82,6 +90,7 @@
         assertEquals(schedules, DvrScheduleManager.getConflictingSchedules(schedules, 0));
     }
 
+    @Test
     public void testGetConflictingSchedules_conflict() {
         long priority = 0;
         long channelId = 0;
@@ -160,6 +169,7 @@
         MoreAsserts.assertEmpty(DvrScheduleManager.getConflictingSchedules(schedules, 5));
     }
 
+    @Test
     public void testGetConflictingSchedules_conflict2() {
         // The case when there is a long schedule.
         long priority = 0;
@@ -186,6 +196,7 @@
         MoreAsserts.assertEmpty(DvrScheduleManager.getConflictingSchedules(schedules, 2));
     }
 
+    @Test
     public void testGetConflictingSchedules_reverseOrder() {
         long priority = 0;
         long channelId = 0;
@@ -264,6 +275,7 @@
         MoreAsserts.assertEmpty(DvrScheduleManager.getConflictingSchedules(schedules, 5));
     }
 
+    @Test
     public void testGetConflictingSchedules_period1() {
         long priority = 0;
         long channelId = 0;
@@ -281,6 +293,7 @@
                 Collections.singletonList(new Range<>(110L, 120L))), r1);
     }
 
+    @Test
     public void testGetConflictingSchedules_period2() {
         long priority = 0;
         long channelId = 0;
@@ -298,6 +311,7 @@
                 Collections.singletonList(new Range<>(110L, 120L))), r1);
     }
 
+    @Test
     public void testGetConflictingSchedules_period3() {
         long priority = 0;
         long channelId = 0;
@@ -328,6 +342,7 @@
                 ranges), r2, r1);
     }
 
+    @Test
     public void testGetConflictingSchedules_addSchedules1() {
         long priority = 0;
         long channelId = 0;
@@ -351,6 +366,7 @@
                 schedules, 1), r1);
     }
 
+    @Test
     public void testGetConflictingSchedules_addSchedules2() {
         long priority = 0;
         long channelId = 0;
@@ -374,6 +390,7 @@
                 schedules, 1), r2, r1);
     }
 
+    @Test
     public void testGetConflictingSchedules_addLowestPriority() {
         long priority = 0;
         long channelId = 0;
@@ -394,6 +411,7 @@
                 schedules, 1), r1);
     }
 
+    @Test
     public void testGetConflictingSchedules_sameChannel() {
         long priority = 0;
         long channelId = 1;
@@ -405,6 +423,7 @@
         MoreAsserts.assertEmpty(DvrScheduleManager.getConflictingSchedules(schedules, 3));
     }
 
+    @Test
     public void testGetConflictingSchedule_startEarlyAndFail() {
         long priority = 0;
         long channelId = 0;
@@ -423,6 +442,7 @@
                 r2);
     }
 
+    @Test
     public void testGetConflictingSchedule_startLate() {
         long priority = 0;
         long channelId = 0;
@@ -441,6 +461,7 @@
                 r2, r1);
     }
 
+    @Test
     public void testGetConflictingSchedulesForTune_canTune() {
         // Can tune to the recorded channel if tuner count is 1.
         long priority = 0;
@@ -452,6 +473,7 @@
                 channelId, 0L, priority + 1, schedules, 1));
     }
 
+    @Test
     public void testGetConflictingSchedulesForTune_cannotTune() {
         // Can't tune to a channel if other channel is recording and tuner count is 1.
         long priority = 0;
@@ -463,6 +485,7 @@
                 INPUT_ID, channelId + 1, 0L, priority + 1, schedules, 1), schedules.get(0));
     }
 
+    @Test
     public void testGetConflictingSchedulesForWatching_otherChannels() {
         // The other channels are to be recorded.
         long priority = 0;
@@ -481,6 +504,7 @@
                 INPUT_ID, channelToWatch, 0L, ++priority, schedules, 2), r1);
     }
 
+    @Test
     public void testGetConflictingSchedulesForWatching_sameChannel1() {
         long priority = 0;
         long channelToWatch = 1;
@@ -498,6 +522,7 @@
                 INPUT_ID, channelToWatch, 0L, ++priority, schedules, 1), r2);
     }
 
+    @Test
     public void testGetConflictingSchedulesForWatching_sameChannel2() {
         long priority = 0;
         long channelToWatch = 1;
@@ -515,6 +540,7 @@
                 INPUT_ID, channelToWatch, 0L, ++priority, schedules, 1), r1);
     }
 
+    @Test
     public void testGetConflictingSchedulesForWatching_sameChannelConflict1() {
         long priority = 0;
         long channelToWatch = 1;
@@ -537,6 +563,7 @@
                 INPUT_ID, channelToWatch, 0L, ++priority, schedules, 1), r2, r1);
     }
 
+    @Test
     public void testGetConflictingSchedulesForWatching_sameChannelConflict2() {
         long priority = 0;
         long channelToWatch = 1;
@@ -559,6 +586,7 @@
                 INPUT_ID, channelToWatch, 0L, ++priority, schedules, 1), r3, r1);
     }
 
+    @Test
     public void testPartiallyConflictingSchedules() {
         long priority = 100;
         long channelId = 0;
@@ -586,49 +614,80 @@
                 RecordingTestUtils.createTestRecordingWithPriorityAndPeriod(++channelId,
                         --priority, 50L, 900L)
         ));
-        Map<ScheduledRecording, Boolean> conflictsInfo = DvrScheduleManager
-                .getConflictingSchedulesInfo(schedules, 1);
+        List<ConflictInfo> conflicts = DvrScheduleManager.getConflictingSchedulesInfo(schedules, 1);
 
-        assertNull(conflictsInfo.get(schedules.get(0)));
-        assertFalse(conflictsInfo.get(schedules.get(1)));
-        assertTrue(conflictsInfo.get(schedules.get(2)));
-        assertTrue(conflictsInfo.get(schedules.get(3)));
-        assertNull(conflictsInfo.get(schedules.get(4)));
-        assertTrue(conflictsInfo.get(schedules.get(5)));
-        assertNull(conflictsInfo.get(schedules.get(6)));
-        assertFalse(conflictsInfo.get(schedules.get(7)));
-        assertFalse(conflictsInfo.get(schedules.get(8)));
-        assertFalse(conflictsInfo.get(schedules.get(9)));
-        assertFalse(conflictsInfo.get(schedules.get(10)));
+        assertNotInList(schedules.get(0), conflicts);
+        assertFullConflict(schedules.get(1), conflicts);
+        assertPartialConflict(schedules.get(2), conflicts);
+        assertPartialConflict(schedules.get(3), conflicts);
+        assertNotInList(schedules.get(4), conflicts);
+        assertPartialConflict(schedules.get(5), conflicts);
+        assertNotInList(schedules.get(6), conflicts);
+        assertFullConflict(schedules.get(7), conflicts);
+        assertFullConflict(schedules.get(8), conflicts);
+        assertFullConflict(schedules.get(9), conflicts);
+        assertFullConflict(schedules.get(10), conflicts);
 
-        conflictsInfo = DvrScheduleManager
-                .getConflictingSchedulesInfo(schedules, 2);
+        conflicts = DvrScheduleManager.getConflictingSchedulesInfo(schedules, 2);
 
-        assertNull(conflictsInfo.get(schedules.get(0)));
-        assertNull(conflictsInfo.get(schedules.get(1)));
-        assertNull(conflictsInfo.get(schedules.get(2)));
-        assertNull(conflictsInfo.get(schedules.get(3)));
-        assertNull(conflictsInfo.get(schedules.get(4)));
-        assertNull(conflictsInfo.get(schedules.get(5)));
-        assertNull(conflictsInfo.get(schedules.get(6)));
-        assertFalse(conflictsInfo.get(schedules.get(7)));
-        assertFalse(conflictsInfo.get(schedules.get(8)));
-        assertFalse(conflictsInfo.get(schedules.get(9)));
-        assertTrue(conflictsInfo.get(schedules.get(10)));
+        assertNotInList(schedules.get(0), conflicts);
+        assertNotInList(schedules.get(1), conflicts);
+        assertNotInList(schedules.get(2), conflicts);
+        assertNotInList(schedules.get(3), conflicts);
+        assertNotInList(schedules.get(4), conflicts);
+        assertNotInList(schedules.get(5), conflicts);
+        assertNotInList(schedules.get(6), conflicts);
+        assertFullConflict(schedules.get(7), conflicts);
+        assertFullConflict(schedules.get(8), conflicts);
+        assertFullConflict(schedules.get(9), conflicts);
+        assertPartialConflict(schedules.get(10), conflicts);
 
-        conflictsInfo = DvrScheduleManager
-                .getConflictingSchedulesInfo(schedules, 3);
+        conflicts = DvrScheduleManager.getConflictingSchedulesInfo(schedules, 3);
 
-        assertNull(conflictsInfo.get(schedules.get(0)));
-        assertNull(conflictsInfo.get(schedules.get(1)));
-        assertNull(conflictsInfo.get(schedules.get(2)));
-        assertNull(conflictsInfo.get(schedules.get(3)));
-        assertNull(conflictsInfo.get(schedules.get(4)));
-        assertNull(conflictsInfo.get(schedules.get(5)));
-        assertNull(conflictsInfo.get(schedules.get(6)));
-        assertNull(conflictsInfo.get(schedules.get(7)));
-        assertTrue(conflictsInfo.get(schedules.get(8)));
-        assertNull(conflictsInfo.get(schedules.get(9)));
-        assertTrue(conflictsInfo.get(schedules.get(10)));
+        assertNotInList(schedules.get(0), conflicts);
+        assertNotInList(schedules.get(1), conflicts);
+        assertNotInList(schedules.get(2), conflicts);
+        assertNotInList(schedules.get(3), conflicts);
+        assertNotInList(schedules.get(4), conflicts);
+        assertNotInList(schedules.get(5), conflicts);
+        assertNotInList(schedules.get(6), conflicts);
+        assertNotInList(schedules.get(7), conflicts);
+        assertPartialConflict(schedules.get(8), conflicts);
+        assertNotInList(schedules.get(9), conflicts);
+        assertPartialConflict(schedules.get(10), conflicts);
+    }
+
+    private void assertNotInList(ScheduledRecording schedule, List<ConflictInfo> conflicts) {
+        for (ConflictInfo conflictInfo : conflicts) {
+            if (conflictInfo.schedule.equals(schedule)) {
+                fail(schedule + " conflicts with others.");
+            }
+        }
+    }
+
+    private void assertPartialConflict(ScheduledRecording schedule, List<ConflictInfo> conflicts) {
+        for (ConflictInfo conflictInfo : conflicts) {
+            if (conflictInfo.schedule.equals(schedule)) {
+                if (conflictInfo.partialConflict) {
+                    return;
+                } else {
+                    fail(schedule + " fully conflicts with others.");
+                }
+            }
+        }
+        fail(schedule + " doesn't conflict");
+    }
+
+    private void assertFullConflict(ScheduledRecording schedule, List<ConflictInfo> conflicts) {
+        for (ConflictInfo conflictInfo : conflicts) {
+            if (conflictInfo.schedule.equals(schedule)) {
+                if (!conflictInfo.partialConflict) {
+                    return;
+                } else {
+                    fail(schedule + " partially conflicts with others.");
+                }
+            }
+        }
+        fail(schedule + " doesn't conflict");
     }
 }
\ No newline at end of file
diff --git a/tests/unit/src/com/android/tv/dvr/EpisodicProgramLoadTaskTest.java b/tests/unit/src/com/android/tv/dvr/EpisodicProgramLoadTaskTest.java
deleted file mode 100644
index 2172d48..0000000
--- a/tests/unit/src/com/android/tv/dvr/EpisodicProgramLoadTaskTest.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2016 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.dvr;
-
-import android.os.Build;
-import android.support.test.filters.SdkSuppress;
-import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
-
-import com.android.tv.dvr.EpisodicProgramLoadTask.ScheduledEpisode;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Tests for {@link EpisodicProgramLoadTask}
- */
-@SmallTest
-@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
-public class EpisodicProgramLoadTaskTest extends AndroidTestCase {
-    private static final long SERIES_RECORDING_ID1 = 1;
-    private static final long SERIES_RECORDING_ID2 = 2;
-    private static final String SEASON_NUMBER1 = "SEASON NUMBER1";
-    private static final String SEASON_NUMBER2 = "SEASON NUMBER2";
-    private static final String EPISODE_NUMBER1 = "EPISODE NUMBER1";
-    private static final String EPISODE_NUMBER2 = "EPISODE NUMBER2";
-
-    public void testEpisodeAlreadyScheduled_true() {
-        List<ScheduledEpisode> episodes = new ArrayList<>();
-        ScheduledEpisode episode = new ScheduledEpisode(SERIES_RECORDING_ID1, SEASON_NUMBER1,
-                EPISODE_NUMBER1);
-        episodes.add(episode);
-        assertTrue(EpisodicProgramLoadTask.isEpisodeScheduled(episodes,
-                new ScheduledEpisode(SERIES_RECORDING_ID1, SEASON_NUMBER1, EPISODE_NUMBER1)));
-    }
-
-    public void testEpisodeAlreadyScheduled_false() {
-        List<ScheduledEpisode> episodes = new ArrayList<>();
-        ScheduledEpisode episode = new ScheduledEpisode(SERIES_RECORDING_ID1, SEASON_NUMBER1,
-                EPISODE_NUMBER1);
-        episodes.add(episode);
-        assertFalse(EpisodicProgramLoadTask.isEpisodeScheduled(episodes,
-                new ScheduledEpisode(SERIES_RECORDING_ID2, SEASON_NUMBER1, EPISODE_NUMBER1)));
-        assertFalse(EpisodicProgramLoadTask.isEpisodeScheduled(episodes,
-                new ScheduledEpisode(SERIES_RECORDING_ID1, SEASON_NUMBER2, EPISODE_NUMBER1)));
-        assertFalse(EpisodicProgramLoadTask.isEpisodeScheduled(episodes,
-                new ScheduledEpisode(SERIES_RECORDING_ID1, SEASON_NUMBER1, EPISODE_NUMBER2)));
-    }
-
-    public void testEpisodeAlreadyScheduled_null() {
-        List<ScheduledEpisode> episodes = new ArrayList<>();
-        ScheduledEpisode episode = new ScheduledEpisode(SERIES_RECORDING_ID1, SEASON_NUMBER1,
-                EPISODE_NUMBER1);
-        episodes.add(episode);
-        assertFalse(EpisodicProgramLoadTask.isEpisodeScheduled(episodes,
-                new ScheduledEpisode(SERIES_RECORDING_ID1, null, EPISODE_NUMBER1)));
-        assertFalse(EpisodicProgramLoadTask.isEpisodeScheduled(episodes,
-                new ScheduledEpisode(SERIES_RECORDING_ID1, SEASON_NUMBER1, null)));
-        assertFalse(EpisodicProgramLoadTask.isEpisodeScheduled(episodes,
-                new ScheduledEpisode(SERIES_RECORDING_ID1, null, null)));
-    }
-}
diff --git a/tests/unit/src/com/android/tv/dvr/ScheduledRecordingTest.java b/tests/unit/src/com/android/tv/dvr/ScheduledRecordingTest.java
index 9603641..b98af60 100644
--- a/tests/unit/src/com/android/tv/dvr/ScheduledRecordingTest.java
+++ b/tests/unit/src/com/android/tv/dvr/ScheduledRecordingTest.java
@@ -16,34 +16,37 @@
 
 package com.android.tv.dvr;
 
-import static com.android.tv.testing.dvr.RecordingTestUtils
-        .createTestRecordingWithIdAndPeriod;
+import static com.android.tv.testing.dvr.RecordingTestUtils.createTestRecordingWithIdAndPeriod;
 import static com.android.tv.testing.dvr.RecordingTestUtils.normalizePriority;
+import static junit.framework.TestCase.assertEquals;
 
+import android.os.Build;
+import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
 import android.test.MoreAsserts;
 import android.util.Range;
 
 import com.android.tv.data.Channel;
 import com.android.tv.data.Program;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.testing.dvr.RecordingTestUtils;
 
-import junit.framework.TestCase;
+import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
-/**
- * Tests for {@link ScheduledRecordingTest}
- */
+/** Tests for {@link ScheduledRecordingTest} */
 @SmallTest
-public class ScheduledRecordingTest extends TestCase {
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public class ScheduledRecordingTest {
     private static final String INPUT_ID = "input_id";
     private static final int CHANNEL_ID = 273;
 
-    public void testIsOverLapping() throws Exception {
+    @Test
+    public void testIsOverLapping() {
         ScheduledRecording r = createTestRecordingWithIdAndPeriod(1, INPUT_ID, CHANNEL_ID,
                 10L, 20L);
         assertOverLapping(false, 1L, 9L, r);
@@ -59,6 +62,7 @@
         assertOverLapping(false, 21L, 29L, r);
     }
 
+    @Test
     public void testBuildProgram() {
         Channel c = new Channel.Builder().build();
         Program p = new Program.Builder().build();
@@ -67,12 +71,14 @@
         assertEquals("type", ScheduledRecording.TYPE_PROGRAM, actual.getType());
     }
 
+    @Test
     public void testBuildTime() {
         ScheduledRecording actual = createTestRecordingWithIdAndPeriod(1, INPUT_ID, CHANNEL_ID,
                 10L, 20L);
         assertEquals("type", ScheduledRecording.TYPE_TIMED, actual.getType());
     }
 
+    @Test
     public void testBuildFrom() {
         ScheduledRecording expected = createTestRecordingWithIdAndPeriod(1, INPUT_ID, CHANNEL_ID,
                 10L, 20L);
@@ -80,6 +86,7 @@
         RecordingTestUtils.assertRecordingEquals(expected, actual);
     }
 
+    @Test
     public void testBuild_priority() {
         ScheduledRecording a = normalizePriority(
                 createTestRecordingWithIdAndPeriod(1, INPUT_ID, CHANNEL_ID, 10L, 20L));
diff --git a/tests/unit/src/com/android/tv/dvr/SeriesRecordingTest.java b/tests/unit/src/com/android/tv/dvr/data/SeriesRecordingTest.java
similarity index 95%
rename from tests/unit/src/com/android/tv/dvr/SeriesRecordingTest.java
rename to tests/unit/src/com/android/tv/dvr/data/SeriesRecordingTest.java
index c48fec0..790b2ee 100644
--- a/tests/unit/src/com/android/tv/dvr/SeriesRecordingTest.java
+++ b/tests/unit/src/com/android/tv/dvr/data/SeriesRecordingTest.java
@@ -14,7 +14,9 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.data;
+
+import static org.junit.Assert.assertEquals;
 
 import android.os.Build;
 import android.os.Parcel;
@@ -23,14 +25,14 @@
 
 import com.android.tv.data.Program;
 
-import junit.framework.TestCase;
+import org.junit.Test;
 
 /**
  * Tests for {@link SeriesRecording}.
  */
 @SmallTest
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
-public class SeriesRecordingTest extends TestCase {
+public class SeriesRecordingTest {
     private static final String PROGRAM_TITLE = "MyProgram";
     private static final long CHANNEL_ID = 123;
     private static final long OTHER_CHANNEL_ID = 321;
@@ -46,7 +48,8 @@
     private final Program mBaseProgram = new Program.Builder().setTitle(PROGRAM_TITLE)
             .setChannelId(CHANNEL_ID).setSeriesId(SERIES_ID).build();
 
-    public void testParcelable() throws Exception {
+    @Test
+    public void testParcelable() {
         SeriesRecording r1 = new SeriesRecording.Builder()
                 .setId(1)
                 .setChannelId(2)
@@ -77,20 +80,24 @@
         }
     }
 
+    @Test
     public void testDoesProgramMatch_simpleMatch() {
         assertDoesProgramMatch(mBaseProgram, mBaseSeriesRecording, true);
     }
 
+    @Test
     public void testDoesProgramMatch_differentSeriesId() {
         Program program = new Program.Builder(mBaseProgram).setSeriesId(OTHER_SERIES_ID).build();
         assertDoesProgramMatch(program, mBaseSeriesRecording, false);
     }
 
+    @Test
     public void testDoesProgramMatch_differentChannel() {
         Program program = new Program.Builder(mBaseProgram).setChannelId(OTHER_CHANNEL_ID).build();
         assertDoesProgramMatch(program, mBaseSeriesRecording, false);
     }
 
+    @Test
     public void testDoesProgramMatch_startFromSeason2() {
         Program program = mBaseProgram;
         assertDoesProgramMatch(program, mSeriesRecordingSeason2, true);
@@ -102,6 +109,7 @@
         assertDoesProgramMatch(program, mSeriesRecordingSeason2, true);
     }
 
+    @Test
     public void testDoesProgramMatch_startFromSeason2episode5() {
         Program program = mBaseProgram;
         assertDoesProgramMatch(program, mSeriesRecordingSeason2Episode5, true);
diff --git a/tests/unit/src/com/android/tv/dvr/DvrDbSyncTest.java b/tests/unit/src/com/android/tv/dvr/provider/DvrDbSyncTest.java
similarity index 74%
rename from tests/unit/src/com/android/tv/dvr/DvrDbSyncTest.java
rename to tests/unit/src/com/android/tv/dvr/provider/DvrDbSyncTest.java
index 7cb3721..94f88a5 100644
--- a/tests/unit/src/com/android/tv/dvr/DvrDbSyncTest.java
+++ b/tests/unit/src/com/android/tv/dvr/provider/DvrDbSyncTest.java
@@ -14,8 +14,10 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.provider;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.never;
@@ -25,20 +27,26 @@
 import android.os.Build;
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 
 import com.android.tv.data.ChannelDataManager;
 import com.android.tv.data.Program;
+import com.android.tv.dvr.DvrDataManagerImpl;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.data.SeriesRecording;
+import com.android.tv.dvr.recorder.SeriesRecordingScheduler;
 
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 /**
- * Tests for {@link DvrScheduleManager}
+ * Tests for {@link com.android.tv.dvr.DvrScheduleManager}
  */
 @SmallTest
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
-public class DvrDbSyncTest extends AndroidTestCase {
+public class DvrDbSyncTest {
     private static final String INPUT_ID = "input_id";
     private static final long BASE_PROGRAM_ID = 1;
     private static final long BASE_START_TIME_MS = 0;
@@ -47,28 +55,39 @@
     private static final String BASE_EPISODE_NUMBER = "3";
     private static final Program BASE_PROGRAM = new Program.Builder().setId(BASE_PROGRAM_ID)
             .setStartTimeUtcMillis(BASE_START_TIME_MS).setEndTimeUtcMillis(BASE_END_TIME_MS)
+            .build();
+    private static final Program BASE_SERIES_PROGRAM = new Program.Builder().setId(BASE_PROGRAM_ID)
+            .setStartTimeUtcMillis(BASE_START_TIME_MS).setEndTimeUtcMillis(BASE_END_TIME_MS)
             .setSeasonNumber(BASE_SEASON_NUMBER).setEpisodeNumber(BASE_EPISODE_NUMBER).build();
     private static final ScheduledRecording BASE_SCHEDULE =
             ScheduledRecording.builder(INPUT_ID, BASE_PROGRAM).build();
+    private static final ScheduledRecording BASE_SERIES_SCHEDULE =
+            ScheduledRecording.builder(INPUT_ID, BASE_SERIES_PROGRAM).build();
 
     private DvrDbSync mDbSync;
+    @Mock private DvrManager mDvrManager;
     @Mock private DvrDataManagerImpl mDataManager;
     @Mock private ChannelDataManager mChannelDataManager;
+    @Mock private SeriesRecordingScheduler mSeriesRecordingScheduler;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
         when(mChannelDataManager.isDbLoadFinished()).thenReturn(true);
-        mDbSync = new DvrDbSync(getContext(), mDataManager, mChannelDataManager);
+        when(mDvrManager.addSeriesRecording(anyObject(), anyObject(), anyInt()))
+                .thenReturn(SeriesRecording.builder(INPUT_ID, BASE_PROGRAM).build());
+        mDbSync = new DvrDbSync(getContext(), mDataManager, mChannelDataManager,
+                mDvrManager, mSeriesRecordingScheduler);
     }
 
+    @Test
     public void testHandleUpdateProgram_null() {
         addSchedule(BASE_PROGRAM_ID, BASE_SCHEDULE);
         mDbSync.handleUpdateProgram(null, BASE_PROGRAM_ID);
         verify(mDataManager).removeScheduledRecording(BASE_SCHEDULE);
     }
 
+    @Test
     public void testHandleUpdateProgram_changeTimeNotStarted() {
         addSchedule(BASE_PROGRAM_ID, BASE_SCHEDULE);
         long startTimeMs = BASE_START_TIME_MS + 1;
@@ -79,6 +98,7 @@
         assertUpdateScheduleCalled(program);
     }
 
+    @Test
     public void testHandleUpdateProgram_changeTimeInProgressNotCalled() {
         addSchedule(BASE_PROGRAM_ID, ScheduledRecording.buildFrom(BASE_SCHEDULE)
                 .setState(ScheduledRecording.STATE_RECORDING_IN_PROGRESS).build());
@@ -89,22 +109,24 @@
         verify(mDataManager, never()).updateScheduledRecording(anyObject());
     }
 
+    @Test
     public void testHandleUpdateProgram_changeSeason() {
-        addSchedule(BASE_PROGRAM_ID, BASE_SCHEDULE);
+        addSchedule(BASE_PROGRAM_ID, BASE_SERIES_SCHEDULE);
         String seasonNumber = BASE_SEASON_NUMBER + "1";
         String episodeNumber = BASE_EPISODE_NUMBER + "1";
-        Program program = new Program.Builder(BASE_PROGRAM).setSeasonNumber(seasonNumber)
+        Program program = new Program.Builder(BASE_SERIES_PROGRAM).setSeasonNumber(seasonNumber)
                 .setEpisodeNumber(episodeNumber).build();
         mDbSync.handleUpdateProgram(program, BASE_PROGRAM_ID);
         assertUpdateScheduleCalled(program);
     }
 
+    @Test
     public void testHandleUpdateProgram_finished() {
-        addSchedule(BASE_PROGRAM_ID, ScheduledRecording.buildFrom(BASE_SCHEDULE)
+        addSchedule(BASE_PROGRAM_ID, ScheduledRecording.buildFrom(BASE_SERIES_SCHEDULE)
                 .setState(ScheduledRecording.STATE_RECORDING_FINISHED).build());
         String seasonNumber = BASE_SEASON_NUMBER + "1";
         String episodeNumber = BASE_EPISODE_NUMBER + "1";
-        Program program = new Program.Builder(BASE_PROGRAM).setSeasonNumber(seasonNumber)
+        Program program = new Program.Builder(BASE_SERIES_PROGRAM).setSeasonNumber(seasonNumber)
                 .setEpisodeNumber(episodeNumber).build();
         mDbSync.handleUpdateProgram(program, BASE_PROGRAM_ID);
         verify(mDataManager, never()).updateScheduledRecording(anyObject());
diff --git a/tests/unit/src/com/android/tv/dvr/provider/EpisodicProgramLoadTaskTest.java b/tests/unit/src/com/android/tv/dvr/provider/EpisodicProgramLoadTaskTest.java
new file mode 100644
index 0000000..216d4d5
--- /dev/null
+++ b/tests/unit/src/com/android/tv/dvr/provider/EpisodicProgramLoadTaskTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 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.dvr.provider;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Build;
+import android.support.test.filters.SdkSuppress;
+import android.support.test.filters.SmallTest;
+
+import com.android.tv.dvr.data.SeasonEpisodeNumber;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link EpisodicProgramLoadTask}
+ */
+@SmallTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public class EpisodicProgramLoadTaskTest {
+    private static final long SERIES_RECORDING_ID1 = 1;
+    private static final long SERIES_RECORDING_ID2 = 2;
+    private static final String SEASON_NUMBER1 = "SEASON NUMBER1";
+    private static final String SEASON_NUMBER2 = "SEASON NUMBER2";
+    private static final String EPISODE_NUMBER1 = "EPISODE NUMBER1";
+    private static final String EPISODE_NUMBER2 = "EPISODE NUMBER2";
+
+    @Test
+    public void testEpisodeAlreadyScheduled_true() {
+        List<SeasonEpisodeNumber> seasonEpisodeNumbers = new ArrayList<>();
+        SeasonEpisodeNumber seasonEpisodeNumber = new SeasonEpisodeNumber(
+                SERIES_RECORDING_ID1, SEASON_NUMBER1, EPISODE_NUMBER1);
+        seasonEpisodeNumbers.add(seasonEpisodeNumber);
+        assertTrue(seasonEpisodeNumbers.contains(
+                new SeasonEpisodeNumber(SERIES_RECORDING_ID1, SEASON_NUMBER1, EPISODE_NUMBER1)));
+    }
+
+    @Test
+    public void testEpisodeAlreadyScheduled_false() {
+        List<SeasonEpisodeNumber> seasonEpisodeNumbers = new ArrayList<>();
+        SeasonEpisodeNumber seasonEpisodeNumber = new SeasonEpisodeNumber(
+                SERIES_RECORDING_ID1, SEASON_NUMBER1, EPISODE_NUMBER1);
+        seasonEpisodeNumbers.add(seasonEpisodeNumber);
+        assertFalse(seasonEpisodeNumbers.contains(
+                new SeasonEpisodeNumber(SERIES_RECORDING_ID2, SEASON_NUMBER1, EPISODE_NUMBER1)));
+        assertFalse(seasonEpisodeNumbers.contains(
+                new SeasonEpisodeNumber(SERIES_RECORDING_ID1, SEASON_NUMBER2, EPISODE_NUMBER1)));
+        assertFalse(seasonEpisodeNumbers.contains(
+                new SeasonEpisodeNumber(SERIES_RECORDING_ID1, SEASON_NUMBER1, EPISODE_NUMBER2)));
+    }
+
+    @Test
+    public void testEpisodeAlreadyScheduled_null() {
+        List<SeasonEpisodeNumber> seasonEpisodeNumbers = new ArrayList<>();
+        SeasonEpisodeNumber seasonEpisodeNumber = new SeasonEpisodeNumber(
+                SERIES_RECORDING_ID1, SEASON_NUMBER1, EPISODE_NUMBER1);
+        seasonEpisodeNumbers.add(seasonEpisodeNumber);
+        assertFalse(seasonEpisodeNumbers.contains(
+                new SeasonEpisodeNumber(SERIES_RECORDING_ID1, null, EPISODE_NUMBER1)));
+        assertFalse(seasonEpisodeNumbers.contains(
+                new SeasonEpisodeNumber(SERIES_RECORDING_ID1, SEASON_NUMBER1, null)));
+        assertFalse(seasonEpisodeNumbers.contains(
+                new SeasonEpisodeNumber(SERIES_RECORDING_ID1, null, null)));
+    }
+}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/tv/dvr/recorder/DvrRecordingServiceTest.java b/tests/unit/src/com/android/tv/dvr/recorder/DvrRecordingServiceTest.java
new file mode 100644
index 0000000..8f7dcaf
--- /dev/null
+++ b/tests/unit/src/com/android/tv/dvr/recorder/DvrRecordingServiceTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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.dvr.recorder;
+
+import static org.mockito.Mockito.verify;
+
+import android.content.Intent;
+import android.os.Build;
+import android.support.test.filters.SdkSuppress;
+import android.support.test.filters.SmallTest;
+import android.test.ServiceTestCase;
+
+import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.feature.TestableFeature;
+
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link DvrRecordingService}.
+ */
+@SmallTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public class DvrRecordingServiceTest
+        extends ServiceTestCase<DvrRecordingServiceTest.MockDvrRecordingService> {
+    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDvrFeature.enableForTest();
+        MockitoAnnotations.initMocks(this);
+        setupService();
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mDvrFeature.resetForTests();
+        super.tearDown();
+    }
+
+    public DvrRecordingServiceTest() {
+        super(MockDvrRecordingService.class);
+    }
+
+    public void testStartService_null() throws Exception {
+        // Not recording
+        startService(null);
+        assertFalse(getService().mInForeground);
+
+        // Recording
+        getService().startRecording();
+        startService(null);
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mIsRecording);
+        getService().reset();
+    }
+
+    public void testStartService_noUpcomingRecording() throws Exception {
+        Intent intent = new Intent(getContext(), DvrRecordingServiceTest.class);
+        intent.putExtra(DvrRecordingService.EXTRA_START_FOR_RECORDING, false);
+
+        // Not recording
+        startService(intent);
+        assertTrue(getService().mInForeground);
+        assertFalse(getService().mForegroundForUpcomingRecording);
+        getService().stopForegroundIfNotRecordingInternal();
+        assertFalse(getService().mInForeground);
+
+        // Recording, ended quickly
+        getService().startRecording();
+        startService(intent);
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mForegroundForUpcomingRecording);
+        assertTrue(getService().mIsRecording);
+        getService().stopRecording();
+        assertFalse(getService().mInForeground);
+        assertFalse(getService().mIsRecording);
+        getService().stopForegroundIfNotRecordingInternal();
+        assertFalse(getService().mInForeground);
+        assertFalse(getService().mIsRecording);
+        getService().reset();
+
+        // Recording, ended later
+        getService().startRecording();
+        startService(intent);
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mForegroundForUpcomingRecording);
+        assertTrue(getService().mIsRecording);
+        getService().stopForegroundIfNotRecordingInternal();
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mForegroundForUpcomingRecording);
+        assertTrue(getService().mIsRecording);
+        getService().stopRecording();
+        assertFalse(getService().mInForeground);
+        assertFalse(getService().mIsRecording);
+        getService().reset();
+    }
+
+    public void testStartService_hasUpcomingRecording() throws Exception {
+        Intent intent = new Intent(getContext(), DvrRecordingServiceTest.class);
+        intent.putExtra(DvrRecordingService.EXTRA_START_FOR_RECORDING, true);
+
+        // Not recording
+        startService(intent);
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mForegroundForUpcomingRecording);
+        assertFalse(getService().mIsRecording);
+        getService().startRecording();
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mForegroundForUpcomingRecording);
+        assertTrue(getService().mIsRecording);
+        getService().stopRecording();
+        assertFalse(getService().mInForeground);
+        assertFalse(getService().mIsRecording);
+        getService().reset();
+
+        // Recording
+        getService().startRecording();
+        startService(intent);
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mForegroundForUpcomingRecording);
+        assertTrue(getService().mIsRecording);
+        getService().startRecording();
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mForegroundForUpcomingRecording);
+        assertTrue(getService().mIsRecording);
+        getService().stopRecording();
+        assertTrue(getService().mInForeground);
+        assertTrue(getService().mForegroundForUpcomingRecording);
+        assertTrue(getService().mIsRecording);
+        getService().stopRecording();
+        assertFalse(getService().mInForeground);
+        assertFalse(getService().mIsRecording);
+        getService().reset();
+    }
+
+    public static class MockDvrRecordingService extends DvrRecordingService {
+        private int mRecordingCount = 0;
+        private boolean mInForeground;
+        private boolean mForegroundForUpcomingRecording;
+
+        @Override
+        protected void startForegroundInternal(boolean hasUpcomingRecording) {
+            mForegroundForUpcomingRecording = hasUpcomingRecording;
+            mInForeground = true;
+        }
+
+        @Override
+        protected void stopForegroundInternal() {
+            mInForeground = false;
+        }
+
+        private void startRecording() {
+            mOnRecordingSessionChangeListener.onRecordingSessionChange(true, ++mRecordingCount);
+        }
+
+        private void stopRecording() {
+            mOnRecordingSessionChangeListener.onRecordingSessionChange(false, --mRecordingCount);
+        }
+
+        private void reset() {
+            mRecordingCount = 0;
+            mInForeground = false;
+            mIsRecording = false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/tv/dvr/InputTaskSchedulerTest.java b/tests/unit/src/com/android/tv/dvr/recorder/InputTaskSchedulerTest.java
similarity index 85%
rename from tests/unit/src/com/android/tv/dvr/InputTaskSchedulerTest.java
rename to tests/unit/src/com/android/tv/dvr/recorder/InputTaskSchedulerTest.java
index 85c78ce..e5c27e2 100644
--- a/tests/unit/src/com/android/tv/dvr/InputTaskSchedulerTest.java
+++ b/tests/unit/src/com/android/tv/dvr/recorder/InputTaskSchedulerTest.java
@@ -14,13 +14,15 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.after;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -28,21 +30,25 @@
 import android.app.AlarmManager;
 import android.media.tv.TvInputInfo;
 import android.os.Build;
-import android.os.Handler;
 import android.os.Looper;
+import android.os.SystemClock;
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 
 import com.android.tv.InputSessionManager;
 import com.android.tv.data.Channel;
 import com.android.tv.data.ChannelDataManager;
-import com.android.tv.dvr.InputTaskScheduler.RecordingTaskFactory;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.WritableDvrDataManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.recorder.InputTaskScheduler.RecordingTaskFactory;
 import com.android.tv.testing.FakeClock;
 import com.android.tv.testing.dvr.RecordingTestUtils;
 import com.android.tv.util.Clock;
 import com.android.tv.util.TestUtils;
 
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -55,7 +61,7 @@
  */
 @SmallTest
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
-public class InputTaskSchedulerTest extends AndroidTestCase {
+public class InputTaskSchedulerTest {
     private static final String INPUT_ID = "input_id";
     private static final int CHANNEL_ID = 1;
     private static final long LISTENER_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(1);
@@ -73,21 +79,18 @@
     @Mock private ChannelDataManager mChannelDataManager;
     private List<RecordingTask> mRecordingTasks;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
         if (Looper.myLooper() == null) {
             Looper.prepare();
         }
-        Handler fakeMainHandler = new Handler();
-        Handler workerThreadHandler = new Handler();
         mRecordingTasks = new ArrayList();
         MockitoAnnotations.initMocks(this);
         mFakeClock = FakeClock.createWithCurrentTime();
         TvInputInfo input = createTvInputInfo(TUNER_COUNT_ONE);
         mScheduler = new InputTaskScheduler(getContext(), input, Looper.myLooper(),
                 mChannelDataManager, mDvrManager, mDataManager, mSessionManager, mFakeClock,
-                fakeMainHandler, workerThreadHandler, new RecordingTaskFactory() {
+                new RecordingTaskFactory() {
                     @Override
                     public RecordingTask createRecordingTask(ScheduledRecording scheduledRecording,
                             Channel channel, DvrManager dvrManager,
@@ -102,12 +105,8 @@
                 });
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    public void testAddSchedule_past() throws Exception {
+    @Test
+    public void testAddSchedule_past() {
         ScheduledRecording r = RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID,
                 CHANNEL_ID, 0L, 1L);
         when(mDataManager.getScheduledRecording(anyLong())).thenReturn(r);
@@ -118,7 +117,8 @@
                         eq(ScheduledRecording.STATE_RECORDING_FAILED));
     }
 
-    public void testAddSchedule_start() throws Exception {
+    @Test
+    public void testAddSchedule_start() {
         mScheduler.handleAddSchedule(RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID,
                 CHANNEL_ID, mFakeClock.currentTimeMillis(),
                 mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(1)));
@@ -126,7 +126,8 @@
         verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start();
     }
 
-    public void testAddSchedule_consecutiveNoStop() throws Exception {
+    @Test
+    public void testAddSchedule_consecutiveNoStop() {
         long startTimeMs = mFakeClock.currentTimeMillis();
         long endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1);
         long id = 0;
@@ -143,10 +144,12 @@
         verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start();
         // The first schedule should not be stopped because the second one should wait for the end
         // of the first schedule.
-        verify(mRecordingTasks.get(0), after((int) LISTENER_TIMEOUT_MS).never()).stop();
+        SystemClock.sleep(LISTENER_TIMEOUT_MS);
+        verify(mRecordingTasks.get(0), never()).stop();
     }
 
-    public void testAddSchedule_consecutiveNoFail() throws Exception {
+    @Test
+    public void testAddSchedule_consecutiveNoFail() {
         long startTimeMs = mFakeClock.currentTimeMillis();
         long endTimeMs = startTimeMs + TimeUnit.SECONDS.toMillis(1);
         long id = 0;
@@ -163,13 +166,16 @@
                         LOW_PRIORITY, startTimeMs, endTimeMs));
         mScheduler.handleBuildSchedule();
         verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start();
-        verify(mRecordingTasks.get(0), after((int) LISTENER_TIMEOUT_MS).never()).stop();
+        SystemClock.sleep(LISTENER_TIMEOUT_MS);
+        verify(mRecordingTasks.get(0), never()).stop();
         // The second schedule should not fail because it can starts after the first one finishes.
-        verify(mDataManager, after((int) LISTENER_TIMEOUT_MS).never())
+        SystemClock.sleep(LISTENER_TIMEOUT_MS);
+        verify(mDataManager, never())
                 .changeState(any(ScheduledRecording.class),
                         eq(ScheduledRecording.STATE_RECORDING_FAILED));
     }
 
+    @Test
     public void testAddSchedule_consecutiveUseLessSession() throws Exception {
         TvInputInfo input = createTvInputInfo(TUNER_COUNT_TWO);
         mScheduler.updateTvInputInfo(input);
@@ -187,23 +193,27 @@
                         HIGH_PRIORITY, startTimeMs, endTimeMs));
         mScheduler.handleBuildSchedule();
         verify(mRecordingTasks.get(0), timeout((int) LISTENER_TIMEOUT_MS).times(1)).start();
-        verify(mRecordingTasks.get(0), after((int) LISTENER_TIMEOUT_MS).never()).stop();
+        SystemClock.sleep(LISTENER_TIMEOUT_MS);
+        verify(mRecordingTasks.get(0), never()).stop();
         // The second schedule should wait until the first one finishes rather than creating a new
         // session even though there are available tuners.
         assertTrue(mRecordingTasks.size() == 1);
     }
 
-    public void testUpdateSchedule_noCancel() throws Exception {
+    @Test
+    public void testUpdateSchedule_noCancel() {
         ScheduledRecording r = RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID,
                 CHANNEL_ID, mFakeClock.currentTimeMillis(),
                 mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(1));
         mScheduler.handleAddSchedule(r);
         mScheduler.handleBuildSchedule();
         mScheduler.handleUpdateSchedule(r);
-        verify(mRecordingTasks.get(0), after((int) LISTENER_TIMEOUT_MS).never()).cancel();
+        SystemClock.sleep(LISTENER_TIMEOUT_MS);
+        verify(mRecordingTasks.get(0), never()).cancel();
     }
 
-    public void testUpdateSchedule_cancel() throws Exception {
+    @Test
+    public void testUpdateSchedule_cancel() {
         ScheduledRecording r = RecordingTestUtils.createTestRecordingWithPeriod(INPUT_ID,
                 CHANNEL_ID, mFakeClock.currentTimeMillis(),
                 mFakeClock.currentTimeMillis() + TimeUnit.HOURS.toMillis(2));
diff --git a/tests/unit/src/com/android/tv/dvr/RecordingTaskTest.java b/tests/unit/src/com/android/tv/dvr/recorder/RecordingTaskTest.java
similarity index 76%
rename from tests/unit/src/com/android/tv/dvr/RecordingTaskTest.java
rename to tests/unit/src/com/android/tv/dvr/recorder/RecordingTaskTest.java
index 7404a55..37561a4 100644
--- a/tests/unit/src/com/android/tv/dvr/RecordingTaskTest.java
+++ b/tests/unit/src/com/android/tv/dvr/recorder/RecordingTaskTest.java
@@ -14,17 +14,18 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
-import static org.mockito.hamcrest.MockitoHamcrest.longThat;
 
 import android.os.Build;
 import android.os.Handler;
@@ -32,20 +33,24 @@
 import android.os.Message;
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 
 import com.android.tv.InputSessionManager;
 import com.android.tv.InputSessionManager.RecordingSession;
+import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.feature.TestableFeature;
 import com.android.tv.data.Channel;
-import com.android.tv.dvr.RecordingTask.State;
+import com.android.tv.dvr.DvrDataManagerInMemoryImpl;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.data.ScheduledRecording;
+import com.android.tv.dvr.recorder.RecordingTask.State;
 import com.android.tv.testing.FakeClock;
 import com.android.tv.testing.dvr.RecordingTestUtils;
 
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.compat.ArgumentMatcher;
 
 import java.util.concurrent.TimeUnit;
 
@@ -54,9 +59,9 @@
  */
 @SmallTest
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
-public class RecordingTaskTest extends AndroidTestCase {
+public class RecordingTaskTest {
     private static final long DURATION = TimeUnit.MINUTES.toMillis(30);
-    private static final long START_OFFSET_MS = Scheduler.MS_TO_WAKE_BEFORE_START;
+    private static final long START_OFFSET_MS = RecordingScheduler.MS_TO_WAKE_BEFORE_START;
     private static final String INPUT_ID = "input_id";
     private static final int CHANNEL_ID = 273;
 
@@ -66,10 +71,11 @@
     @Mock DvrManager mDvrManager;
     @Mock InputSessionManager mMockSessionManager;
     @Mock RecordingSession mMockRecordingSession;
+    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
+        mDvrFeature.enableForTest();
         if (Looper.myLooper() == null) {
             Looper.prepare();
         }
@@ -78,6 +84,12 @@
         mDataManager = new DvrDataManagerInMemoryImpl(getContext(), mFakeClock);
     }
 
+    @After
+    public void tearDown() {
+        mDvrFeature.resetForTests();
+    }
+
+    @Test
     public void testHandle_init() {
         Channel channel = createTestChannel();
         ScheduledRecording r = createRecording(channel);
@@ -99,6 +111,7 @@
                 .setDisplayName("Test Ch " + CHANNEL_ID).build();
     }
 
+    @Test
     public void testOnConnected() {
         Channel channel = createTestChannel();
         ScheduledRecording r = createRecording(channel);
@@ -127,40 +140,10 @@
         return recordingTask;
     }
 
-    private void verifySendMessageAt(int what, long when) {
-        verify(mMockHandler).sendMessageAtTime(argThat(messageMatchesWhat(what)), delta(when, 100));
-    }
-
-    private static long delta(final long value, final long delta) {
-        return longThat(new BaseMatcher<Long>() {
-            @Override
-            public boolean matches(Object item) {
-                Long other = (Long) item;
-                return other >= value - delta && other <= value + delta;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("eq " + value + "±" + delta);
-
-            }
-        });
-    }
-
     private Message createMessage(int what) {
         Message msg = new Message();
         msg.setTarget(mMockHandler);
         msg.what = what;
         return msg;
     }
-
-    private static ArgumentMatcher<Message> messageMatchesWhat(final int what) {
-        return new ArgumentMatcher<Message>() {
-            @Override
-            public boolean matchesObject(Object argument) {
-                Message message = (Message) argument;
-                return message.what == what;
-            }
-        };
-    }
-}
+}
\ No newline at end of file
diff --git a/tests/unit/src/com/android/tv/dvr/ScheduledProgramReaperTest.java b/tests/unit/src/com/android/tv/dvr/recorder/ScheduledProgramReaperTest.java
similarity index 74%
rename from tests/unit/src/com/android/tv/dvr/ScheduledProgramReaperTest.java
rename to tests/unit/src/com/android/tv/dvr/recorder/ScheduledProgramReaperTest.java
index 847540c..ca72e13 100644
--- a/tests/unit/src/com/android/tv/dvr/ScheduledProgramReaperTest.java
+++ b/tests/unit/src/com/android/tv/dvr/recorder/ScheduledProgramReaperTest.java
@@ -14,15 +14,27 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Build;
+import android.support.test.filters.SdkSuppress;
+import android.support.test.filters.SmallTest;
 import android.test.MoreAsserts;
 
+import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.feature.TestableFeature;
+import com.android.tv.dvr.DvrDataManagerInMemoryImpl;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.testing.FakeClock;
 import com.android.tv.testing.dvr.RecordingTestUtils;
 
-import junit.framework.TestCase;
-
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -31,7 +43,9 @@
 /**
  * Tests for {@link ScheduledProgramReaper}.
  */
-public class ScheduledProgramReaperTest extends TestCase {
+@SmallTest
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
+public class ScheduledProgramReaperTest {
     private static final String INPUT_ID = "input_id";
     private static final int CHANNEL_ID = 273;
     private static final long DURATION = TimeUnit.HOURS.toMillis(1);
@@ -40,23 +54,30 @@
     private FakeClock mFakeClock;
     private DvrDataManagerInMemoryImpl mDvrDataManager;
     @Mock private DvrManager mDvrManager;
+    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
 
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mDvrFeature.enableForTest();
         mFakeClock = FakeClock.createWithTimeOne();
-        mDvrDataManager = new DvrDataManagerInMemoryImpl(null, mFakeClock);
+        mDvrDataManager = new DvrDataManagerInMemoryImpl(getContext(), mFakeClock);
         mReaper = new ScheduledProgramReaper(mDvrDataManager, mFakeClock);
     }
 
-    public void testRun_noRecordings() {
-        MoreAsserts.assertContentsInAnyOrder(mDvrDataManager.getAllScheduledRecordings());
-        mReaper.run();
-        MoreAsserts.assertContentsInAnyOrder(mDvrDataManager.getAllScheduledRecordings());
+    @After
+    public void tearDown() {
+        mDvrFeature.resetForTests();
     }
 
+    @Test
+    public void testRun_noRecordings() {
+        assertTrue(mDvrDataManager.getAllScheduledRecordings().isEmpty());
+        mReaper.run();
+        assertTrue(mDvrDataManager.getAllScheduledRecordings().isEmpty());
+    }
+
+    @Test
     public void testRun_oneRecordingsTomorrow() {
         ScheduledRecording recording = addNewScheduledRecordingForTomorrow();
         MoreAsserts
@@ -66,6 +87,7 @@
                 .assertContentsInAnyOrder(mDvrDataManager.getAllScheduledRecordings(), recording);
     }
 
+    @Test
     public void testRun_oneRecordingsStarted() {
         ScheduledRecording recording = addNewScheduledRecordingForTomorrow();
         MoreAsserts
@@ -76,6 +98,7 @@
                 .assertContentsInAnyOrder(mDvrDataManager.getAllScheduledRecordings(), recording);
     }
 
+    @Test
     public void testRun_oneRecordingsFinished() {
         ScheduledRecording recording = addNewScheduledRecordingForTomorrow();
         MoreAsserts
@@ -87,6 +110,7 @@
                 .assertContentsInAnyOrder(mDvrDataManager.getAllScheduledRecordings(), recording);
     }
 
+    @Test
     public void testRun_oneRecordingsExpired() {
         ScheduledRecording recording = addNewScheduledRecordingForTomorrow();
         MoreAsserts
@@ -97,10 +121,9 @@
         mFakeClock.increment(TimeUnit.SECONDS, 1);
 
         mReaper.run();
-        MoreAsserts.assertContentsInAnyOrder(
-                "Recordings after reaper at " + com.android.tv.util.Utils
+        assertTrue("Recordings after reaper at " + com.android.tv.util.Utils
                         .toIsoDateTimeString(mFakeClock.currentTimeMillis()),
-                mDvrDataManager.getAllScheduledRecordings());
+                mDvrDataManager.getAllScheduledRecordings().isEmpty());
     }
 
     private ScheduledRecording addNewScheduledRecordingForTomorrow() {
diff --git a/tests/unit/src/com/android/tv/dvr/SchedulerTest.java b/tests/unit/src/com/android/tv/dvr/recorder/SchedulerTest.java
similarity index 64%
rename from tests/unit/src/com/android/tv/dvr/SchedulerTest.java
rename to tests/unit/src/com/android/tv/dvr/recorder/SchedulerTest.java
index 30ac1ff..a515472 100644
--- a/tests/unit/src/com/android/tv/dvr/SchedulerTest.java
+++ b/tests/unit/src/com/android/tv/dvr/recorder/SchedulerTest.java
@@ -14,8 +14,11 @@
  * limitations under the License
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
 
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.verify;
@@ -27,14 +30,21 @@
 import android.os.Looper;
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 
 import com.android.tv.InputSessionManager;
+import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.feature.TestableFeature;
 import com.android.tv.data.ChannelDataManager;
+import com.android.tv.dvr.DvrDataManagerInMemoryImpl;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.data.ScheduledRecording;
 import com.android.tv.testing.FakeClock;
 import com.android.tv.testing.dvr.RecordingTestUtils;
 import com.android.tv.util.TvInputManagerHelper;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
@@ -42,61 +52,69 @@
 import java.util.concurrent.TimeUnit;
 
 /**
- * Tests for {@link Scheduler}.
+ * Tests for {@link RecordingScheduler}.
  */
 @SmallTest
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
-public class SchedulerTest extends AndroidTestCase {
+public class SchedulerTest {
     private static final String INPUT_ID = "input_id";
     private static final int CHANNEL_ID = 273;
 
     private FakeClock mFakeClock;
     private DvrDataManagerInMemoryImpl mDataManager;
-    private Scheduler mScheduler;
+    private RecordingScheduler mScheduler;
     @Mock DvrManager mDvrManager;
     @Mock InputSessionManager mSessionManager;
     @Mock AlarmManager mMockAlarmManager;
     @Mock ChannelDataManager mChannelDataManager;
     @Mock TvInputManagerHelper mInputManager;
+    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
+        mDvrFeature.enableForTest();
         mFakeClock = FakeClock.createWithCurrentTime();
-        mDataManager = new DvrDataManagerInMemoryImpl(getContext(), mFakeClock);
+        mDataManager = new DvrDataManagerInMemoryImpl(getTargetContext(), mFakeClock);
         Mockito.when(mChannelDataManager.isDbLoadFinished()).thenReturn(true);
-        mScheduler = new Scheduler(Looper.myLooper(), mDvrManager, mSessionManager, mDataManager,
-                mChannelDataManager, mInputManager, getContext(), mFakeClock, mMockAlarmManager);
+        mScheduler = new RecordingScheduler(Looper.myLooper(), mDvrManager, mSessionManager, mDataManager,
+                mChannelDataManager, mInputManager, getTargetContext(), mFakeClock,
+                mMockAlarmManager);
     }
 
-    public void testUpdate_none() throws Exception {
-        mScheduler.start();
-        mScheduler.update();
+    @After
+    public void tearDown() {
+        mDvrFeature.resetForTests();
+    }
+
+    @Test
+    public void testUpdate_none() {
+        mScheduler.updateAndStartServiceIfNeeded();
         verifyZeroInteractions(mMockAlarmManager);
     }
 
-    public void testUpdate_nextIn12Hours() throws Exception {
+    @Test
+    public void testUpdate_nextIn12Hours() {
         long now = mFakeClock.currentTimeMillis();
         long startTime = now + TimeUnit.HOURS.toMillis(12);
         ScheduledRecording r = RecordingTestUtils
                 .createTestRecordingWithPeriod(INPUT_ID, CHANNEL_ID, startTime,
                 startTime + TimeUnit.HOURS.toMillis(1));
         mDataManager.addScheduledRecording(r);
-        mScheduler.start();
-        verify(mMockAlarmManager).set(
+        verify(mMockAlarmManager).setExactAndAllowWhileIdle(
                 eq(AlarmManager.RTC_WAKEUP),
-                eq(startTime - Scheduler.MS_TO_WAKE_BEFORE_START),
+                eq(startTime - RecordingScheduler.MS_TO_WAKE_BEFORE_START),
                 any(PendingIntent.class));
         Mockito.reset(mMockAlarmManager);
-        mScheduler.update();
-        verify(mMockAlarmManager).set(
+        mScheduler.updateAndStartServiceIfNeeded();
+        verify(mMockAlarmManager).setExactAndAllowWhileIdle(
                 eq(AlarmManager.RTC_WAKEUP),
-                eq(startTime - Scheduler.MS_TO_WAKE_BEFORE_START),
+                eq(startTime - RecordingScheduler.MS_TO_WAKE_BEFORE_START),
                 any(PendingIntent.class));
     }
 
-    public void testStartsWithin() throws Exception {
+    @Test
+    public void testStartsWithin() {
         long now = mFakeClock.currentTimeMillis();
         long startTime = now + 3;
         ScheduledRecording r = RecordingTestUtils
diff --git a/tests/unit/src/com/android/tv/dvr/SeriesRecordingSchedulerTest.java b/tests/unit/src/com/android/tv/dvr/recorder/SeriesRecordingSchedulerTest.java
similarity index 88%
rename from tests/unit/src/com/android/tv/dvr/SeriesRecordingSchedulerTest.java
rename to tests/unit/src/com/android/tv/dvr/recorder/SeriesRecordingSchedulerTest.java
index efefb93..16fa1ba 100644
--- a/tests/unit/src/com/android/tv/dvr/SeriesRecordingSchedulerTest.java
+++ b/tests/unit/src/com/android/tv/dvr/recorder/SeriesRecordingSchedulerTest.java
@@ -14,18 +14,27 @@
  * limitations under the License.
  */
 
-package com.android.tv.dvr;
+package com.android.tv.dvr.recorder;
+
+import static android.support.test.InstrumentationRegistry.getContext;
 
 import android.os.Build;
 import android.support.test.filters.SdkSuppress;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 import android.util.LongSparseArray;
 
+import com.android.tv.common.feature.CommonFeatures;
+import com.android.tv.common.feature.TestableFeature;
 import com.android.tv.data.Program;
+import com.android.tv.dvr.DvrDataManagerInMemoryImpl;
+import com.android.tv.dvr.data.SeriesRecording;
 import com.android.tv.testing.FakeClock;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -35,7 +44,7 @@
  */
 @SmallTest
 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.N)
-public class SeriesRecordingSchedulerTest extends AndroidTestCase {
+public class SeriesRecordingSchedulerTest {
     private static final String PROGRAM_TITLE = "MyProgram";
     private static final long CHANNEL_ID = 123;
     private static final long SERIES_RECORDING_ID1 = 1;
@@ -49,16 +58,23 @@
             .setTitle(PROGRAM_TITLE).setChannelId(CHANNEL_ID).setSeriesId(SERIES_ID).build();
     private final Program mBaseProgram = new Program.Builder().setTitle(PROGRAM_TITLE)
             .setChannelId(CHANNEL_ID).setSeriesId(SERIES_ID).build();
+    private final TestableFeature mDvrFeature = CommonFeatures.DVR;
 
     private DvrDataManagerInMemoryImpl mDataManager;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
+        mDvrFeature.enableForTest();
         FakeClock fakeClock = FakeClock.createWithCurrentTime();
         mDataManager = new DvrDataManagerInMemoryImpl(getContext(), fakeClock);
     }
 
+    @After
+    public void tearDown() {
+        mDvrFeature.resetForTests();
+    }
+
+    @Test
     public void testPickOneProgramPerEpisode_onePerEpisode() {
         SeriesRecording seriesRecording = SeriesRecording.buildFrom(mBaseSeriesRecording)
                 .setId(SERIES_RECORDING_ID1).build();
@@ -75,6 +91,7 @@
         MoreAsserts.assertContentsInAnyOrder(result.get(SERIES_RECORDING_ID1), program1, program2);
     }
 
+    @Test
     public void testPickOneProgramPerEpisode_manyPerEpisode() {
         SeriesRecording seriesRecording = SeriesRecording.buildFrom(mBaseSeriesRecording)
                 .setId(SERIES_RECORDING_ID1).build();
@@ -95,6 +112,7 @@
         MoreAsserts.assertContentsInAnyOrder(result.get(SERIES_RECORDING_ID1), program1, program3);
     }
 
+    @Test
     public void testPickOneProgramPerEpisode_nullEpisode() {
         SeriesRecording seriesRecording = SeriesRecording.buildFrom(mBaseSeriesRecording)
                 .setId(SERIES_RECORDING_ID1).build();
diff --git a/tests/unit/src/com/android/tv/dvr/ui/SortedArrayAdapterTest.java b/tests/unit/src/com/android/tv/dvr/ui/SortedArrayAdapterTest.java
index a571e62..5667ee6 100644
--- a/tests/unit/src/com/android/tv/dvr/ui/SortedArrayAdapterTest.java
+++ b/tests/unit/src/com/android/tv/dvr/ui/SortedArrayAdapterTest.java
@@ -22,6 +22,9 @@
 
 import junit.framework.TestCase;
 
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Objects;
@@ -31,29 +34,30 @@
  */
 @SmallTest
 public class SortedArrayAdapterTest extends TestCase {
-
-    public static final TestData P1 = TestData.create(1, "one");
-    public static final TestData P2 = TestData.create(2, "before");
-    public static final TestData P3 = TestData.create(3, "other");
-    public static final TestData EXTRA = TestData.create(4, "extra");
+    public static final TestData P1 = TestData.create(1, "c");
+    public static final TestData P2 = TestData.create(2, "b");
+    public static final TestData P3 = TestData.create(3, "a");
+    public static final TestData EXTRA = TestData.create(4, "k");
     private TestSortedArrayAdapter mAdapter;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         mAdapter = new TestSortedArrayAdapter(Integer.MAX_VALUE, null);
     }
 
+    @Test
     public void testContents_empty() {
         assertEmpty();
     }
 
+    @Test
     public void testAdd_one() {
         mAdapter.add(P1);
         assertNotEmpty();
         assertContentsInOrder(mAdapter, P1);
     }
 
+    @Test
     public void testAdd_two() {
         mAdapter.add(P1);
         mAdapter.add(P2);
@@ -61,12 +65,14 @@
         assertContentsInOrder(mAdapter, P2, P1);
     }
 
+    @Test
     public void testSetInitialItems_two() {
         mAdapter.setInitialItems(Arrays.asList(P1, P2));
         assertNotEmpty();
         assertContentsInOrder(mAdapter, P2, P1);
     }
 
+    @Test
     public void testMaxInitialCount() {
         mAdapter = new TestSortedArrayAdapter(1, null);
         mAdapter.setInitialItems(Arrays.asList(P1, P2));
@@ -75,6 +81,7 @@
         assertEquals(mAdapter.get(0), P2);
     }
 
+    @Test
     public void testExtraItem() {
         mAdapter = new TestSortedArrayAdapter(Integer.MAX_VALUE, EXTRA);
         mAdapter.setInitialItems(Arrays.asList(P1, P2));
@@ -88,6 +95,7 @@
         assertEquals(mAdapter.get(0), EXTRA);
     }
 
+    @Test
     public void testExtraItemWithMaxCount() {
         mAdapter = new TestSortedArrayAdapter(1, EXTRA);
         mAdapter.setInitialItems(Arrays.asList(P1, P2));
@@ -100,6 +108,7 @@
         assertEquals(mAdapter.get(0), EXTRA);
     }
 
+    @Test
     public void testRemove() {
         mAdapter.add(P1);
         mAdapter.add(P2);
@@ -111,8 +120,47 @@
         assertContentsInOrder(mAdapter, P1);
         mAdapter.remove(P1);
         assertEmpty();
+        mAdapter.add(P1);
+        mAdapter.add(P2);
+        mAdapter.add(P3);
+        assertContentsInOrder(mAdapter, P3, P2, P1);
+        mAdapter.removeItems(0, 2);
+        assertContentsInOrder(mAdapter, P1);
+        mAdapter.add(P2);
+        mAdapter.add(P3);
+        mAdapter.addExtraItem(EXTRA);
+        assertContentsInOrder(mAdapter, P3, P2, P1, EXTRA);
+        mAdapter.removeItems(1, 1);
+        assertContentsInOrder(mAdapter, P3, P1, EXTRA);
+        mAdapter.removeItems(1, 2);
+        assertContentsInOrder(mAdapter, P3);
+        mAdapter.addExtraItem(EXTRA);
+        mAdapter.addExtraItem(P2);
+        mAdapter.add(P1);
+        assertContentsInOrder(mAdapter, P3, P1, EXTRA, P2);
+        mAdapter.removeItems(1, 2);
+        assertContentsInOrder(mAdapter, P3, P2);
+        mAdapter.add(P1);
+        assertContentsInOrder(mAdapter, P3, P1, P2);
     }
 
+    @Test
+    public void testReplace() {
+        mAdapter.add(P1);
+        mAdapter.add(P2);
+        assertNotEmpty();
+        assertContentsInOrder(mAdapter, P2, P1);
+        mAdapter.replace(1, P3);
+        assertContentsInOrder(mAdapter, P3, P2);
+        mAdapter.replace(0, P1);
+        assertContentsInOrder(mAdapter, P2, P1);
+        mAdapter.addExtraItem(EXTRA);
+        assertContentsInOrder(mAdapter, P2, P1, EXTRA);
+        mAdapter.replace(2, P3);
+        assertContentsInOrder(mAdapter, P2, P1, P3);
+    }
+
+    @Test
     public void testChange_sorting() {
         TestData p2_changed = TestData.create(2, "z changed");
         mAdapter.add(P1);
@@ -123,6 +171,7 @@
         assertContentsInOrder(mAdapter, P1, p2_changed);
     }
 
+    @Test
     public void testChange_new() {
         mAdapter.change(P1);
         assertNotEmpty();
@@ -194,7 +243,7 @@
         }
 
         @Override
-        long getId(TestData item) {
+        protected long getId(TestData item) {
             return item.mId;
         }
     }
diff --git a/tests/unit/src/com/android/tv/experiments/ExperimentsTest.java b/tests/unit/src/com/android/tv/experiments/ExperimentsTest.java
new file mode 100644
index 0000000..3f827ce
--- /dev/null
+++ b/tests/unit/src/com/android/tv/experiments/ExperimentsTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 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.experiments;
+
+import static org.junit.Assert.assertEquals;
+
+import android.support.test.filters.SmallTest;
+
+import com.android.tv.common.BuildConfig;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tests for {@link Experiments}.
+ */
+@SmallTest
+public class ExperimentsTest {
+    @Before
+    public void setUp() {
+        ExperimentFlag.initForTest();
+    }
+
+
+    @Test
+    public void testEngOnlyDefault() {
+        assertEquals("ENABLE_DEVELOPER_FEATURES", Boolean.valueOf(BuildConfig.ENG),
+                Experiments.ENABLE_DEVELOPER_FEATURES.get());
+    }
+
+
+}
diff --git a/tests/unit/src/com/android/tv/menu/MenuTest.java b/tests/unit/src/com/android/tv/menu/MenuTest.java
index 35e2a0f..e8cfdbe 100644
--- a/tests/unit/src/com/android/tv/menu/MenuTest.java
+++ b/tests/unit/src/com/android/tv/menu/MenuTest.java
@@ -15,11 +15,16 @@
  */
 package com.android.tv.menu;
 
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 
 import com.android.tv.menu.Menu.OnMenuVisibilityChangeListener;
 
+import org.junit.Before;
+import org.junit.Test;
 import org.mockito.Matchers;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
@@ -29,23 +34,23 @@
  * Tests for {@link Menu}.
  */
 @SmallTest
-public class MenuTest extends AndroidTestCase {
+public class MenuTest {
     private Menu mMenu;
     private IMenuView mMenuView;
     private OnMenuVisibilityChangeListener mVisibilityChangeListener;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         mMenuView = Mockito.mock(IMenuView.class);
         MenuRowFactory factory = Mockito.mock(MenuRowFactory.class);
         Mockito.when(factory.createMenuRow(Mockito.any(Menu.class), Mockito.any(Class.class)))
                 .thenReturn(null);
         mVisibilityChangeListener = Mockito.mock(OnMenuVisibilityChangeListener.class);
-        mMenu = new Menu(getContext(), mMenuView, factory, mVisibilityChangeListener);
+        mMenu = new Menu(getTargetContext(), mMenuView, factory, mVisibilityChangeListener);
         mMenu.disableAnimationForTest();
     }
 
+    @Test
     public void testScheduleHide() {
         mMenu.show(Menu.REASON_NONE);
         setMenuVisible(true);
@@ -67,6 +72,7 @@
         assertFalse("Hide is scheduled", mMenu.isHideScheduled());
     }
 
+    @Test
     public void testShowHide_ReasonNone() {
         // Show with REASON_NONE
         mMenu.show(Menu.REASON_NONE);
@@ -87,6 +93,7 @@
         Mockito.verify(mMenuView).onHide();
     }
 
+    @Test
     public void testShowHide_ReasonGuide() {
         // Show with REASON_GUIDE
         mMenu.show(Menu.REASON_GUIDE);
@@ -107,6 +114,7 @@
         Mockito.verify(mMenuView).onHide();
     }
 
+    @Test
     public void testShowHide_ReasonPlayControlsFastForward() {
         // Show with REASON_PLAY_CONTROLS_FAST_FORWARD
         mMenu.show(Menu.REASON_PLAY_CONTROLS_FAST_FORWARD);
diff --git a/tests/unit/src/com/android/tv/menu/TvOptionsRowAdapterTest.java b/tests/unit/src/com/android/tv/menu/TvOptionsRowAdapterTest.java
index 6b0726d..49ba851 100644
--- a/tests/unit/src/com/android/tv/menu/TvOptionsRowAdapterTest.java
+++ b/tests/unit/src/com/android/tv/menu/TvOptionsRowAdapterTest.java
@@ -15,18 +15,24 @@
  */
 package com.android.tv.menu;
 
+import static android.support.test.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
 import android.media.tv.TvTrackInfo;
 import android.os.SystemClock;
 import android.support.test.filters.MediumTest;
+import android.text.TextUtils;
 
 import com.android.tv.BaseMainActivityTestCase;
-import com.android.tv.MainActivity;
-import com.android.tv.customization.CustomAction;
 import com.android.tv.testing.Constants;
-import com.android.tv.testing.Utils;
+import com.android.tv.testing.testinput.ChannelState;
 import com.android.tv.testing.testinput.ChannelStateData;
 import com.android.tv.testing.testinput.TvTestInputConstants;
 
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.Collections;
 import java.util.List;
 
@@ -35,24 +41,22 @@
  */
 @MediumTest
 public class TvOptionsRowAdapterTest extends BaseMainActivityTestCase {
-    private static final int WAIT_TRACK_SIZE_TIMEOUT_MS = 300;
-    public static final int TRACK_SIZE_CHECK_INTERVAL_MS = 10;
+    private static final int WAIT_TRACK_EVENT_TIMEOUT_MS = 300;
+    public static final int TRACK_CHECK_INTERVAL_MS = 10;
 
     // TODO: Refactor TvOptionsRowAdapter so it does not rely on MainActivity
     private TvOptionsRowAdapter mTvOptionsRowAdapter;
 
-    public TvOptionsRowAdapterTest() {
-        super(MainActivity.class);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @Before
+    public void setUp() {
         super.setUp();
         mTvOptionsRowAdapter = new TvOptionsRowAdapter(mActivity, Collections.emptyList());
         tuneToChannel(TvTestInputConstants.CH_1_DEFAULT_DONT_MODIFY);
         waitUntilAudioTracksHaveSize(1);
+        waitUntilAudioTrackSelected(ChannelState.DEFAULT.getSelectedAudioTrackId());
         // update should be called on the main thread to avoid the multi-thread problem.
-        Utils.runOnMainSync(new Runnable() {
+        getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {
                 mTvOptionsRowAdapter.update();
@@ -60,11 +64,13 @@
         });
     }
 
+    @Test
     public void testUpdateAudioAction_2tracks() {
         ChannelStateData data = new ChannelStateData();
         data.mTvTrackInfos.add(Constants.GENERIC_AUDIO_TRACK);
         updateThenTune(data, TvTestInputConstants.CH_2);
         waitUntilAudioTracksHaveSize(2);
+        waitUntilAudioTrackSelected(Constants.EN_STEREO_AUDIO_TRACK.getId());
 
         boolean result = mTvOptionsRowAdapter.updateMultiAudioAction();
         assertEquals("update Action had change", true, result);
@@ -72,46 +78,87 @@
                 MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled());
     }
 
+    @Test
     public void testUpdateAudioAction_1track() {
         ChannelStateData data = new ChannelStateData();
         data.mTvTrackInfos.clear();
         data.mTvTrackInfos.add(Constants.GENERIC_AUDIO_TRACK);
+        data.mSelectedVideoTrackId = null;
+        data.mSelectedAudioTrackId = Constants.GENERIC_AUDIO_TRACK.getId();
         updateThenTune(data, TvTestInputConstants.CH_2);
         waitUntilAudioTracksHaveSize(1);
+        waitUntilAudioTrackSelected(Constants.GENERIC_AUDIO_TRACK.getId());
 
         boolean result = mTvOptionsRowAdapter.updateMultiAudioAction();
-        assertEquals("update Action had change", false, result);
+        assertEquals("update Action had change", true, result);
         assertEquals("Multi Audio enabled", false,
                 MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled());
     }
 
+    @Test
     public void testUpdateAudioAction_noTracks() {
         ChannelStateData data = new ChannelStateData();
         data.mTvTrackInfos.clear();
+        data.mTvTrackInfos.add(ChannelState.DEFAULT_VIDEO_TRACK);
+        data.mSelectedVideoTrackId = ChannelState.DEFAULT_VIDEO_TRACK.getId();
+        data.mSelectedAudioTrackId = null;
         updateThenTune(data, TvTestInputConstants.CH_2);
-        waitUntilAudioTracksHaveSize(0);
+        // Wait for the video tracks, because there's no audio track.
+        waitUntilVideoTracksHaveSize(1);
+        waitUntilVideoTrackSelected(data.mSelectedVideoTrackId);
 
         boolean result = mTvOptionsRowAdapter.updateMultiAudioAction();
-        assertEquals("update Action had change", false, result);
+        assertEquals("update Action had change", true, result);
         assertEquals("Multi Audio enabled", false,
                 MenuAction.SELECT_AUDIO_LANGUAGE_ACTION.isEnabled());
     }
 
     private void waitUntilAudioTracksHaveSize(int expected) {
+        waitUntilTracksHaveSize(TvTrackInfo.TYPE_AUDIO, expected);
+    }
+
+    private void waitUntilVideoTracksHaveSize(int expected) {
+        waitUntilTracksHaveSize(TvTrackInfo.TYPE_VIDEO, expected);
+    }
+
+    private void waitUntilTracksHaveSize(int trackType, int expected) {
         long start = SystemClock.elapsedRealtime();
         int size = -1;
-        while (SystemClock.elapsedRealtime() < start + WAIT_TRACK_SIZE_TIMEOUT_MS) {
+        while (SystemClock.elapsedRealtime() < start + WAIT_TRACK_EVENT_TIMEOUT_MS) {
             getInstrumentation().waitForIdleSync();
-            List<TvTrackInfo> tracks = mActivity.getTracks(TvTrackInfo.TYPE_AUDIO);
+            List<TvTrackInfo> tracks = mActivity.getTracks(trackType);
             if (tracks != null) {
                 size = tracks.size();
                 if (size == expected) {
                     return;
                 }
             }
-            SystemClock.sleep(TRACK_SIZE_CHECK_INTERVAL_MS);
+            SystemClock.sleep(TRACK_CHECK_INTERVAL_MS);
         }
-        fail("Waited for " + WAIT_TRACK_SIZE_TIMEOUT_MS + " milliseconds for track size to be "
+        fail("Waited for " + WAIT_TRACK_EVENT_TIMEOUT_MS + " milliseconds for track size to be "
                 + expected + " but was " + size);
     }
+
+    private void waitUntilAudioTrackSelected(String trackId) {
+        waitUntilTrackSelected(TvTrackInfo.TYPE_AUDIO, trackId);
+    }
+
+    private void waitUntilVideoTrackSelected(String trackId) {
+        waitUntilTrackSelected(TvTrackInfo.TYPE_VIDEO, trackId);
+    }
+
+    private void waitUntilTrackSelected(int trackType, String trackId) {
+        long start = SystemClock.elapsedRealtime();
+        String selectedTrackId = null;
+        while (SystemClock.elapsedRealtime() < start + WAIT_TRACK_EVENT_TIMEOUT_MS) {
+            getInstrumentation().waitForIdleSync();
+            selectedTrackId = mActivity.getSelectedTrack(trackType);
+            if (TextUtils.equals(selectedTrackId, trackId)) {
+                return;
+            }
+            SystemClock.sleep(TRACK_CHECK_INTERVAL_MS);
+        }
+        fail("Waited for " + WAIT_TRACK_EVENT_TIMEOUT_MS + " milliseconds for track ID to be "
+                + trackId + " but was " + selectedTrackId);
+    }
 }
diff --git a/tests/unit/src/com/android/tv/recommendation/ChannelRecordTest.java b/tests/unit/src/com/android/tv/recommendation/ChannelRecordTest.java
index c76de8f..db76510 100644
--- a/tests/unit/src/com/android/tv/recommendation/ChannelRecordTest.java
+++ b/tests/unit/src/com/android/tv/recommendation/ChannelRecordTest.java
@@ -16,11 +16,16 @@
 
 package com.android.tv.recommendation;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+import static org.junit.Assert.assertEquals;
+
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 
 import com.android.tv.testing.Utils;
 
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.Random;
 import java.util.concurrent.TimeUnit;
 
@@ -28,31 +33,33 @@
  * Unit tests for {@link ChannelRecord}.
  */
 @SmallTest
-public class ChannelRecordTest extends AndroidTestCase {
+public class ChannelRecordTest {
     private static final int CHANNEL_RECORD_MAX_HISTORY_SIZE = ChannelRecord.MAX_HISTORY_SIZE;
 
     private Random mRandom;
     private ChannelRecord mChannelRecord;
     private long mLatestWatchEndTimeMs;
 
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         mLatestWatchEndTimeMs = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
         mChannelRecord = new ChannelRecord(getContext(), null, false);
         mRandom = Utils.createTestRandom();
     }
 
+    @Test
     public void testGetLastWatchEndTime_noHistory() {
         assertEquals(0, mChannelRecord.getLastWatchEndTimeMs());
     }
 
+    @Test
     public void testGetLastWatchEndTime_oneHistory() {
         addWatchLog();
 
         assertEquals(mLatestWatchEndTimeMs, mChannelRecord.getLastWatchEndTimeMs());
     }
 
+    @Test
     public void testGetLastWatchEndTime_maxHistories() {
         for (int i = 0; i < CHANNEL_RECORD_MAX_HISTORY_SIZE; ++i) {
             addWatchLog();
@@ -61,6 +68,7 @@
         assertEquals(mLatestWatchEndTimeMs, mChannelRecord.getLastWatchEndTimeMs());
     }
 
+    @Test
     public void testGetLastWatchEndTime_moreThanMaxHistories() {
         for (int i = 0; i < CHANNEL_RECORD_MAX_HISTORY_SIZE + 1; ++i) {
             addWatchLog();
@@ -69,16 +77,19 @@
         assertEquals(mLatestWatchEndTimeMs, mChannelRecord.getLastWatchEndTimeMs());
     }
 
+    @Test
     public void testGetTotalWatchDuration_noHistory() {
         assertEquals(0, mChannelRecord.getTotalWatchDurationMs());
     }
 
+    @Test
     public void testGetTotalWatchDuration_oneHistory() {
         long durationMs = addWatchLog();
 
         assertEquals(durationMs, mChannelRecord.getTotalWatchDurationMs());
     }
 
+    @Test
     public void testGetTotalWatchDuration_maxHistories() {
         long totalWatchTimeMs = 0;
         for (int i = 0; i < CHANNEL_RECORD_MAX_HISTORY_SIZE; ++i) {
@@ -89,6 +100,7 @@
         assertEquals(totalWatchTimeMs, mChannelRecord.getTotalWatchDurationMs());
     }
 
+    @Test
     public void testGetTotalWatchDuration_moreThanMaxHistories() {
         long totalWatchTimeMs = 0;
         long firstDurationMs = 0;
diff --git a/tests/unit/src/com/android/tv/recommendation/EvaluatorTestCase.java b/tests/unit/src/com/android/tv/recommendation/EvaluatorTestCase.java
index 0255947..853fb24 100644
--- a/tests/unit/src/com/android/tv/recommendation/EvaluatorTestCase.java
+++ b/tests/unit/src/com/android/tv/recommendation/EvaluatorTestCase.java
@@ -16,30 +16,35 @@
 
 package com.android.tv.recommendation;
 
-import android.test.AndroidTestCase;
+import static android.support.test.InstrumentationRegistry.getContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import com.android.tv.data.Channel;
 import com.android.tv.recommendation.RecommendationUtils.ChannelRecordSortedMapHelper;
 import com.android.tv.recommendation.Recommender.Evaluator;
 import com.android.tv.testing.Utils;
 
+import org.junit.Before;
+
 import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Base test case for Recommendation Evaluator Unit tests.
  */
-public abstract class EvaluatorTestCase<T extends Evaluator> extends AndroidTestCase {
+public abstract class EvaluatorTestCase<T extends Evaluator> {
     private static final long INVALID_CHANNEL_ID = -1;
 
+    private static final double SCORE_DELTA = 0.01;
+
     private ChannelRecordSortedMapHelper mChannelRecordSortedMap;
     private RecommendationDataManager mDataManager;
 
     public T mEvaluator;
 
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         mChannelRecordSortedMap = new ChannelRecordSortedMapHelper(getContext());
         mDataManager = RecommendationUtils
                 .createMockRecommendationDataManager(mChannelRecordSortedMap);
@@ -91,8 +96,9 @@
      * Check whether scores of each channels are valid.
      */
     protected void assertChannelScoresValid() {
-        assertEquals(Evaluator.NOT_RECOMMENDED, mEvaluator.evaluateChannel(INVALID_CHANNEL_ID));
-        assertEquals(Evaluator.NOT_RECOMMENDED,
+        assertEqualScores(Evaluator.NOT_RECOMMENDED,
+                mEvaluator.evaluateChannel(INVALID_CHANNEL_ID));
+        assertEqualScores(Evaluator.NOT_RECOMMENDED,
                 mEvaluator.evaluateChannel(mChannelRecordSortedMap.size()));
 
         for (long channelId : mChannelRecordSortedMap.keySet()) {
@@ -109,6 +115,14 @@
         mEvaluator.onChannelRecordListChanged(new ArrayList<>(mChannelRecordSortedMap.values()));
     }
 
+    void assertEqualScores(double expected, double actual) {
+        assertEquals(expected, actual, SCORE_DELTA);
+    }
+
+    void assertEqualScores(String message, double expected, double actual) {
+        assertEquals(message, expected, actual, SCORE_DELTA);
+    }
+
     private class FakeRecommender extends Recommender {
         public FakeRecommender() {
             super(new Recommender.Listener() {
@@ -120,7 +134,7 @@
                 public void onRecommendationChanged() {
                 }
             }, true, mDataManager);
-    }
+        }
 
         @Override
         public ChannelRecord getChannelRecord(long channelId) {
diff --git a/tests/unit/src/com/android/tv/recommendation/FavoriteChannelEvaluatorTest.java b/tests/unit/src/com/android/tv/recommendation/FavoriteChannelEvaluatorTest.java
index aae3a93..ac701af 100644
--- a/tests/unit/src/com/android/tv/recommendation/FavoriteChannelEvaluatorTest.java
+++ b/tests/unit/src/com/android/tv/recommendation/FavoriteChannelEvaluatorTest.java
@@ -16,8 +16,12 @@
 
 package com.android.tv.recommendation;
 
+import static org.junit.Assert.assertTrue;
+
 import android.support.test.filters.SmallTest;
 
+import org.junit.Test;
+
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
@@ -38,14 +42,16 @@
         return new FavoriteChannelEvaluator();
     }
 
+    @Test
     public void testOneChannelWithNoWatchLog() {
         long channelId = addChannel().getId();
         notifyChannelAndWatchLogLoaded();
 
-        assertEquals(Recommender.Evaluator.NOT_RECOMMENDED,
+        assertEqualScores(Recommender.Evaluator.NOT_RECOMMENDED,
                 mEvaluator.evaluateChannel(channelId));
     }
 
+    @Test
     public void testOneChannelWithRandomWatchLogs() {
         addChannel();
         addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
@@ -55,17 +61,19 @@
         assertChannelScoresValid();
     }
 
+    @Test
     public void testMultiChannelsWithNoWatchLog() {
         addChannels(DEFAULT_NUMBER_OF_CHANNELS);
         notifyChannelAndWatchLogLoaded();
 
         List<Long> channelIdList = getChannelIdListSorted();
         for (long channelId : channelIdList) {
-            assertEquals(Recommender.Evaluator.NOT_RECOMMENDED,
+            assertEqualScores(Recommender.Evaluator.NOT_RECOMMENDED,
                     mEvaluator.evaluateChannel(channelId));
         }
     }
 
+    @Test
     public void testMultiChannelsWithRandomWatchLogs() {
         addChannels(DEFAULT_NUMBER_OF_CHANNELS);
         addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
@@ -75,6 +83,7 @@
         assertChannelScoresValid();
     }
 
+    @Test
     public void testMultiChannelsWithSimpleWatchLogs() {
         addChannels(DEFAULT_NUMBER_OF_CHANNELS);
         // For two channels which has ID x and y (x < y), the channel y is more watched
@@ -99,6 +108,7 @@
         }
     }
 
+    @Test
     public void testTwoChannelsWithSameWatchDuration() {
         long channelOne = addChannel().getId();
         long channelTwo = addChannel().getId();
@@ -112,6 +122,7 @@
                 mEvaluator.evaluateChannel(channelTwo));
     }
 
+    @Test
     public void testTwoChannelsWithDifferentWatchDuration() {
         long channelOne = addChannel().getId();
         long channelTwo = addChannel().getId();
@@ -131,6 +142,7 @@
         assertTrue(mEvaluator.evaluateChannel(channelOne) > mEvaluator.evaluateChannel(channelTwo));
     }
 
+    @Test
     public void testScoreIncreasesWithNewWatchLog() {
         long channelId = addChannel().getId();
         addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
diff --git a/tests/unit/src/com/android/tv/recommendation/RecentChannelEvaluatorTest.java b/tests/unit/src/com/android/tv/recommendation/RecentChannelEvaluatorTest.java
index 55a4e4a..8f09223 100644
--- a/tests/unit/src/com/android/tv/recommendation/RecentChannelEvaluatorTest.java
+++ b/tests/unit/src/com/android/tv/recommendation/RecentChannelEvaluatorTest.java
@@ -16,8 +16,12 @@
 
 package com.android.tv.recommendation;
 
+import static org.junit.Assert.assertTrue;
+
 import android.support.test.filters.SmallTest;
 
+import org.junit.Test;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -40,14 +44,16 @@
         return new RecentChannelEvaluator();
     }
 
+    @Test
     public void testOneChannelWithNoWatchLog() {
         long channelId = addChannel().getId();
         notifyChannelAndWatchLogLoaded();
 
-        assertEquals(Recommender.Evaluator.NOT_RECOMMENDED,
+        assertEqualScores(Recommender.Evaluator.NOT_RECOMMENDED,
                 mEvaluator.evaluateChannel(channelId));
     }
 
+    @Test
     public void testOneChannelWithRandomWatchLogs() {
         addChannel();
         addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
@@ -57,17 +63,19 @@
         assertChannelScoresValid();
     }
 
+    @Test
     public void testMultiChannelsWithNoWatchLog() {
         addChannels(DEFAULT_NUMBER_OF_CHANNELS);
         notifyChannelAndWatchLogLoaded();
 
         List<Long> channelIdList = getChannelIdListSorted();
         for (long channelId : channelIdList) {
-            assertEquals(Recommender.Evaluator.NOT_RECOMMENDED,
+            assertEqualScores(Recommender.Evaluator.NOT_RECOMMENDED,
                     mEvaluator.evaluateChannel(channelId));
         }
     }
 
+    @Test
     public void testMultiChannelsWithRandomWatchLogs() {
         addChannels(DEFAULT_NUMBER_OF_CHANNELS);
         addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
@@ -77,6 +85,7 @@
         assertChannelScoresValid();
     }
 
+    @Test
     public void testMultiChannelsWithSimpleWatchLogs() {
         addChannels(DEFAULT_NUMBER_OF_CHANNELS);
         // Every channel has one watch log with 1 hour. Also, for two channels
@@ -99,6 +108,7 @@
         }
     }
 
+    @Test
     public void testScoreIncreasesWithNewWatchLog() {
         addChannels(DEFAULT_NUMBER_OF_CHANNELS);
         addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
@@ -119,6 +129,7 @@
         }
     }
 
+    @Test
     public void testScoreDecreasesWithIncrementOfWatchedLogUpdatedTime() {
         addChannels(DEFAULT_NUMBER_OF_CHANNELS);
         addRandomWatchLogs(DEFAULT_WATCH_START_TIME_MS, DEFAULT_WATCH_END_TIME_MS,
diff --git a/tests/unit/src/com/android/tv/recommendation/RecommendationUtils.java b/tests/unit/src/com/android/tv/recommendation/RecommendationUtils.java
index 4a61399..b00ed16 100644
--- a/tests/unit/src/com/android/tv/recommendation/RecommendationUtils.java
+++ b/tests/unit/src/com/android/tv/recommendation/RecommendationUtils.java
@@ -34,7 +34,6 @@
 import java.util.concurrent.TimeUnit;
 
 public class RecommendationUtils {
-    private static final String TAG = "RecommendationUtils";
     private static final long INVALID_CHANNEL_ID = -1;
 
     /**
diff --git a/tests/unit/src/com/android/tv/recommendation/RecommenderTest.java b/tests/unit/src/com/android/tv/recommendation/RecommenderTest.java
index 5270ffc..85524a8 100644
--- a/tests/unit/src/com/android/tv/recommendation/RecommenderTest.java
+++ b/tests/unit/src/com/android/tv/recommendation/RecommenderTest.java
@@ -16,14 +16,21 @@
 
 package com.android.tv.recommendation;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 import android.test.MoreAsserts;
 
 import com.android.tv.data.Channel;
 import com.android.tv.recommendation.RecommendationUtils.ChannelRecordSortedMapHelper;
 import com.android.tv.testing.Utils;
 
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -34,7 +41,7 @@
 import java.util.concurrent.TimeUnit;
 
 @SmallTest
-public class RecommenderTest extends AndroidTestCase {
+public class RecommenderTest {
     private static final int DEFAULT_NUMBER_OF_CHANNELS = 5;
     private static final long DEFAULT_WATCH_START_TIME_MS =
             System.currentTimeMillis() - TimeUnit.DAYS.toMillis(2);
@@ -72,16 +79,15 @@
     private Channel mChannel_3;
     private Channel mChannel_4;
 
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-
+    @Before
+    public void setUp() {
         mChannelRecordSortedMap = new ChannelRecordSortedMapHelper(getContext());
         mDataManager = RecommendationUtils
                 .createMockRecommendationDataManager(mChannelRecordSortedMap);
         mChannelRecordSortedMap.resetRandom(Utils.createTestRandom());
     }
 
+    @Test
     public void testRecommendChannels_includeRecommendedOnly_allChannelsHaveNoScore() {
         createRecommender(true, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
 
@@ -94,6 +100,7 @@
         assertEquals(0, mRecommender.recommendChannels(5).size());
     }
 
+    @Test
     public void testRecommendChannels_notIncludeRecommendedOnly_allChannelsHaveNoScore() {
         createRecommender(false, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
 
@@ -106,6 +113,7 @@
         assertEquals(4, mRecommender.recommendChannels(5).size());
     }
 
+    @Test
     public void testRecommendChannels_includeRecommendedOnly_allChannelsHaveScore() {
         createRecommender(true, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
 
@@ -125,6 +133,7 @@
                 mChannel_4, mChannel_3, mChannel_2, mChannel_1);
     }
 
+    @Test
     public void testRecommendChannels_notIncludeRecommendedOnly_allChannelsHaveScore() {
         createRecommender(false, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
 
@@ -144,6 +153,7 @@
                 mChannel_4, mChannel_3, mChannel_2, mChannel_1);
     }
 
+    @Test
     public void testRecommendChannels_includeRecommendedOnly_fewChannelsHaveScore() {
         createRecommender(true, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
 
@@ -163,6 +173,7 @@
                 mChannel_1, mChannel_2);
     }
 
+    @Test
     public void testRecommendChannels_notIncludeRecommendedOnly_fewChannelsHaveScore() {
         createRecommender(false, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
 
@@ -189,6 +200,7 @@
                 mChannel_1, mChannel_2);
     }
 
+    @Test
     public void testGetChannelSortKey_recommendAllChannels() {
         createRecommender(true, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
 
@@ -203,6 +215,7 @@
         assertSortKeyNotInvalid(channelList);
     }
 
+    @Test
     public void testGetChannelSortKey_recommendFewChannels() {
         // Test with recommending 3 channels.
         createRecommender(true, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
@@ -221,6 +234,7 @@
         assertSortKeyNotInvalid(channelList);
     }
 
+    @Test
     public void testListener_onRecommendationChanged() {
         createRecommender(true, START_DATAMANAGER_RUNNABLE_ADD_FOUR_CHANNELS);
         // FakeEvaluator doesn't recommend a channel with empty watch log. As every channel
@@ -245,6 +259,7 @@
         assertTrue(mOnRecommendationChanged);
     }
 
+    @Test
     public void testListener_onRecommenderReady() {
         createRecommender(true, new Runnable() {
             @Override
diff --git a/tests/unit/src/com/android/tv/recommendation/RoutineWatchEvaluatorTest.java b/tests/unit/src/com/android/tv/recommendation/RoutineWatchEvaluatorTest.java
index c9e21e9..7b8e256 100644
--- a/tests/unit/src/com/android/tv/recommendation/RoutineWatchEvaluatorTest.java
+++ b/tests/unit/src/com/android/tv/recommendation/RoutineWatchEvaluatorTest.java
@@ -16,12 +16,16 @@
 
 package com.android.tv.recommendation;
 
+import static org.junit.Assert.assertEquals;
+
 import android.support.test.filters.SmallTest;
 import android.test.MoreAsserts;
 
 import com.android.tv.data.Program;
 import com.android.tv.recommendation.RoutineWatchEvaluator.ProgramTime;
 
+import org.junit.Test;
+
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.List;
@@ -61,6 +65,7 @@
         return new RoutineWatchEvaluator();
     }
 
+    @Test
     public void testSplitTextToWords() {
         assertSplitTextToWords("");
         assertSplitTextToWords("Google", "Google");
@@ -71,6 +76,7 @@
         assertSplitTextToWords("A.I.", "A.I");
     }
 
+    @Test
     public void testCalculateMaximumMatchedWordSequenceLength() {
         assertMaximumMatchedWordSequenceLength(0, "", "Google");
         assertMaximumMatchedWordSequenceLength(2, "The Big Bang Theory", "Big Bang");
@@ -82,25 +88,29 @@
         assertMaximumMatchedWordSequenceLength(0, "Dexter", "Friends");
     }
 
+    @Test
     public void testCalculateTitleMatchScore_empty() {
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("", ""));
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", ""));
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("", "foo"));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("", ""));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", ""));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("", "foo"));
     }
 
+    @Test
     public void testCalculateTitleMatchScore_spaces() {
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(" ", " "));
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", " "));
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(" ", "foo"));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(" ", " "));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", " "));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(" ", "foo"));
     }
 
 
+    @Test
     public void testCalculateTitleMatchScore_null() {
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(null, null));
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", null));
-        assertEquals(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(null, "foo"));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(null, null));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore("foo", null));
+        assertEqualScores(0.0, RoutineWatchEvaluator.calculateTitleMatchScore(null, "foo"));
     }
 
+    @Test
     public void testCalculateTitleMatchScore_longerMatchIsBetter() {
         String base = "foo bar baz";
         assertInOrder(
@@ -110,6 +120,7 @@
                 score(base, "foo bar baz"));
     }
 
+    @Test
     public void testProgramTime_createFromProgram() {
         Calendar time = Calendar.getInstance();
         int todayDayOfWeek = time.get(Calendar.DAY_OF_WEEK);
@@ -149,6 +160,7 @@
                 programTimeToday1800_3600);
     }
 
+    @Test
     public void testCalculateOverlappedIntervalScore() {
         // Today 21:00 - 24:00.
         ProgramTime programTimeToday2100_2400 = ProgramTime.createFromProgram(
@@ -179,6 +191,7 @@
                 programTimeTomorrow2000_2300);
     }
 
+    @Test
     public void testGetTimeOfDayInSec() {
         // Time was set as 00:00:00. So, getTimeOfDay must returns 0 (= 0 * 60 * 60 + 0 * 60 + 0).
         assertEquals("TimeOfDayInSec", hourMinuteToSec(0, 0),
@@ -222,9 +235,9 @@
             score *= RoutineWatchEvaluator.MULTIPLIER_FOR_UNMATCHED_DAY_OF_WEEK;
         }
         // Two tests for testing commutative law.
-        assertEquals("OverlappedIntervalScore", score,
+        assertEqualScores("OverlappedIntervalScore", score,
                 RoutineWatchEvaluator.calculateOverlappedIntervalScore(t1, t2));
-        assertEquals("OverlappedIntervalScore", score,
+        assertEqualScores("OverlappedIntervalScore", score,
                 RoutineWatchEvaluator.calculateOverlappedIntervalScore(t2, t1));
     }
 
diff --git a/tests/unit/src/com/android/tv/search/LocalSearchProviderTest.java b/tests/unit/src/com/android/tv/search/LocalSearchProviderTest.java
new file mode 100644
index 0000000..b0d342c
--- /dev/null
+++ b/tests/unit/src/com/android/tv/search/LocalSearchProviderTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2017 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.search;
+
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.verify;
+
+import android.app.SearchManager;
+import android.database.Cursor;
+import android.net.Uri;
+import android.support.test.filters.SmallTest;
+import android.test.ProviderTestCase2;
+
+import com.android.tv.ApplicationSingletons;
+import com.android.tv.TvApplication;
+import com.android.tv.perf.PerformanceMonitor;
+import com.android.tv.util.MockApplicationSingletons;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/** Unit test for {@link LocalSearchProvider}. */
+@SmallTest
+public class LocalSearchProviderTest extends ProviderTestCase2<LocalSearchProvider> {
+    private static final String AUTHORITY = "com.android.tv.search";
+    private static final String KEYWORD = "keyword";
+    private static final Uri BASE_SEARCH_URI = Uri.parse("content://" + AUTHORITY + "/"
+            + SearchManager.SUGGEST_URI_PATH_QUERY + "/" + KEYWORD);
+    private static final Uri WRONG_SERACH_URI = Uri.parse("content://" + AUTHORITY + "/wrong_path/"
+            + KEYWORD);
+
+    private ApplicationSingletons mOldAppSingletons;
+    MockApplicationSingletons mMockAppSingletons;
+    @Mock PerformanceMonitor mMockPerformanceMointor;
+    @Mock SearchInterface mMockSearchInterface;
+
+    public LocalSearchProviderTest() {
+        super(LocalSearchProvider.class, AUTHORITY);
+    }
+
+    @Before
+    @Override
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        setContext(getTargetContext());
+        mOldAppSingletons = TvApplication.sAppSingletons;
+        mMockAppSingletons = new MockApplicationSingletons(getTargetContext());
+        mMockAppSingletons.setPerformanceMonitor(mMockPerformanceMointor);
+        TvApplication.sAppSingletons = mMockAppSingletons;
+        super.setUp();
+        getProvider().setSearchInterface(mMockSearchInterface);
+    }
+
+    @After
+    @Override
+    public void tearDown() throws Exception {
+        TvApplication.sAppSingletons = mOldAppSingletons;
+        super.tearDown();
+    }
+
+    @Test
+    public void testQuery_normalUri() {
+        verifyQueryWithArguments(null, null);
+        verifyQueryWithArguments(1, null);
+        verifyQueryWithArguments(null, 1);
+        verifyQueryWithArguments(1, 1);
+    }
+
+    @Test
+    public void testQuery_invalidUri() {
+        try (Cursor c = getProvider().query(WRONG_SERACH_URI, null, null, null, null)) {
+            fail("Query with invalid URI should fail.");
+        } catch (IllegalArgumentException e) {
+            // Success.
+        }
+    }
+
+    @Test
+    public void testQuery_invalidLimit() {
+        verifyQueryWithArguments(-1, null);
+    }
+
+    @Test
+    public void testQuery_invalidAction() {
+        verifyQueryWithArguments(null, SearchInterface.ACTION_TYPE_START - 1);
+        verifyQueryWithArguments(null, SearchInterface.ACTION_TYPE_END + 1);
+    }
+
+    private void verifyQueryWithArguments(Integer limit, Integer action) {
+        Uri uri = BASE_SEARCH_URI;
+        if (limit != null || action != null) {
+            Uri.Builder builder = uri.buildUpon();
+            if (limit != null) {
+                builder.appendQueryParameter(SearchManager.SUGGEST_PARAMETER_LIMIT,
+                        limit.toString());
+            }
+            if (action != null) {
+                builder.appendQueryParameter(LocalSearchProvider.SUGGEST_PARAMETER_ACTION,
+                        action.toString());
+            }
+            uri = builder.build();
+        }
+        try (Cursor c = getProvider().query(uri, null, null, null, null)) {
+            // Do nothing.
+        }
+        int expectedLimit = limit == null || limit <= 0 ?
+                LocalSearchProvider.DEFAULT_SEARCH_LIMIT : limit;
+        int expectedAction = (action == null || action < SearchInterface.ACTION_TYPE_START
+                || action > SearchInterface.ACTION_TYPE_END) ?
+                LocalSearchProvider.DEFAULT_SEARCH_ACTION : action;
+        verify(mMockSearchInterface).search(KEYWORD, expectedLimit, expectedAction);
+        clearInvocations(mMockSearchInterface);
+    }
+}
diff --git a/tests/unit/src/com/android/tv/tests/TvActivityTest.java b/tests/unit/src/com/android/tv/tests/TvActivityTest.java
index 3479785..aa33f77 100644
--- a/tests/unit/src/com/android/tv/tests/TvActivityTest.java
+++ b/tests/unit/src/com/android/tv/tests/TvActivityTest.java
@@ -16,19 +16,28 @@
 
 package com.android.tv.tests;
 
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
 import android.support.test.filters.MediumTest;
-import android.test.ActivityInstrumentationTestCase2;
+import android.support.test.rule.ActivityTestRule;
 
 import com.android.tv.TvActivity;
+import com.android.tv.testing.Utils;
+
+import org.junit.Rule;
+import org.junit.Test;
 
 @MediumTest
-public class TvActivityTest extends ActivityInstrumentationTestCase2<TvActivity> {
+public class TvActivityTest {
+    @Rule
+    public ActivityTestRule<TvActivity> mActivityTestRule =
+            new ActivityTestRule<>(TvActivity.class, false, false);
 
-    public TvActivityTest() {
-        super(TvActivity.class);
-    }
-
+    @Test
     public void testLifeCycle() {
-        getActivity();
+        assertTrue("TvActivity should be enabled.", Utils.isTvActivityEnabled(getTargetContext()));
+        assertNotNull(mActivityTestRule.launchActivity(null));
     }
 }
diff --git a/tests/unit/src/com/android/tv/util/ImageCacheTest.java b/tests/unit/src/com/android/tv/util/ImageCacheTest.java
index e185d5f..a76194b 100644
--- a/tests/unit/src/com/android/tv/util/ImageCacheTest.java
+++ b/tests/unit/src/com/android/tv/util/ImageCacheTest.java
@@ -17,19 +17,21 @@
 package com.android.tv.util;
 
 import static com.android.tv.util.BitmapUtils.createScaledBitmapInfo;
+import static org.junit.Assert.assertSame;
 
 import android.graphics.Bitmap;
 import android.support.test.filters.MediumTest;
 
 import com.android.tv.util.BitmapUtils.ScaledBitmapInfo;
 
-import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.Test;
 
 /**
  * Tests for {@link ImageCache}.
  */
 @MediumTest
-public class ImageCacheTest extends TestCase {
+public class ImageCacheTest {
     private static final Bitmap ORIG = Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565);
 
     private static final String KEY = "same";
@@ -40,14 +42,14 @@
 
     private ImageCache mImageCache;
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() throws Exception {
         mImageCache = ImageCache.newInstance(0.1f);
     }
 
     //TODO: Empty the cache in the setup.  Try using @VisibleForTesting
 
+    @Test
     public void testPutIfLarger_smaller() throws Exception {
 
         mImageCache.putIfNeeded( INFO_50);
@@ -57,6 +59,7 @@
         assertSame("after", INFO_50, mImageCache.get(KEY));
     }
 
+    @Test
     public void testPutIfLarger_larger() throws Exception {
         mImageCache.putIfNeeded( INFO_50);
         assertSame("before", INFO_50, mImageCache.get(KEY));
@@ -65,6 +68,7 @@
         assertSame("after", INFO_100, mImageCache.get(KEY));
     }
 
+    @Test
     public void testPutIfLarger_alreadyMax() throws Exception {
 
         mImageCache.putIfNeeded( INFO_100);
diff --git a/tests/unit/src/com/android/tv/util/MockApplicationSingletons.java b/tests/unit/src/com/android/tv/util/MockApplicationSingletons.java
new file mode 100644
index 0000000..4cfc7f8
--- /dev/null
+++ b/tests/unit/src/com/android/tv/util/MockApplicationSingletons.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2017 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.util;
+
+import android.content.Context;
+
+import com.android.tv.ApplicationSingletons;
+import com.android.tv.InputSessionManager;
+import com.android.tv.MainActivityWrapper;
+import com.android.tv.TvApplication;
+import com.android.tv.analytics.Analytics;
+import com.android.tv.analytics.Tracker;
+import com.android.tv.config.RemoteConfig;
+import com.android.tv.data.ChannelDataManager;
+import com.android.tv.data.PreviewDataManager;
+import com.android.tv.data.ProgramDataManager;
+import com.android.tv.dvr.DvrDataManager;
+import com.android.tv.dvr.DvrManager;
+import com.android.tv.dvr.DvrScheduleManager;
+import com.android.tv.dvr.DvrStorageStatusManager;
+import com.android.tv.dvr.DvrWatchedPositionManager;
+import com.android.tv.dvr.recorder.RecordingScheduler;
+import com.android.tv.perf.PerformanceMonitor;
+
+/**
+ * Mock {@link ApplicationSingletons} class.
+ */
+public class MockApplicationSingletons implements ApplicationSingletons {
+    private final TvApplication mApp;
+
+    private PerformanceMonitor mPerformanceMonitor;
+
+    public MockApplicationSingletons(Context context) {
+        mApp = (TvApplication) context.getApplicationContext();
+    }
+
+    @Override
+    public Analytics getAnalytics() {
+        return mApp.getAnalytics();
+    }
+
+    @Override
+    public ChannelDataManager getChannelDataManager() {
+        return mApp.getChannelDataManager();
+    }
+
+    @Override
+    public boolean isChannelDataManagerLoadFinished() {
+        return mApp.isChannelDataManagerLoadFinished();
+    }
+
+    @Override
+    public ProgramDataManager getProgramDataManager() {
+        return mApp.getProgramDataManager();
+    }
+
+    @Override
+    public boolean isProgramDataManagerCurrentProgramsLoadFinished() {
+        return mApp.isProgramDataManagerCurrentProgramsLoadFinished();
+    }
+
+    @Override
+    public PreviewDataManager getPreviewDataManager() {
+        return mApp.getPreviewDataManager();
+    }
+
+    @Override
+    public DvrDataManager getDvrDataManager() {
+        return mApp.getDvrDataManager();
+    }
+
+    @Override
+    public DvrStorageStatusManager getDvrStorageStatusManager() {
+        return mApp.getDvrStorageStatusManager();
+    }
+
+    @Override
+    public DvrScheduleManager getDvrScheduleManager() {
+        return mApp.getDvrScheduleManager();
+    }
+
+    @Override
+    public DvrManager getDvrManager() {
+        return mApp.getDvrManager();
+    }
+
+    @Override
+    public RecordingScheduler getRecordingScheduler() {
+        return mApp.getRecordingScheduler();
+    }
+
+    @Override
+    public DvrWatchedPositionManager getDvrWatchedPositionManager() {
+        return mApp.getDvrWatchedPositionManager();
+    }
+
+    @Override
+    public InputSessionManager getInputSessionManager() {
+        return mApp.getInputSessionManager();
+    }
+
+    @Override
+    public Tracker getTracker() {
+        return mApp.getTracker();
+    }
+
+    @Override
+    public TvInputManagerHelper getTvInputManagerHelper() {
+        return mApp.getTvInputManagerHelper();
+    }
+
+    @Override
+    public MainActivityWrapper getMainActivityWrapper() {
+        return mApp.getMainActivityWrapper();
+    }
+
+    @Override
+    public AccountHelper getAccountHelper() {
+        return mApp.getAccountHelper();
+    }
+
+    @Override
+    public RemoteConfig getRemoteConfig() {
+        return mApp.getRemoteConfig();
+    }
+
+    @Override
+    public boolean isRunningInMainProcess() {
+        return mApp.isRunningInMainProcess();
+    }
+
+    @Override
+    public PerformanceMonitor getPerformanceMonitor() {
+        return mPerformanceMonitor != null ? mPerformanceMonitor : mApp.getPerformanceMonitor();
+    }
+
+    public void setPerformanceMonitor(PerformanceMonitor performanceMonitor) {
+        mPerformanceMonitor = performanceMonitor;
+    }
+}
diff --git a/tests/unit/src/com/android/tv/util/MultiLongSparseArrayTest.java b/tests/unit/src/com/android/tv/util/MultiLongSparseArrayTest.java
index fe094fb..7335f20 100644
--- a/tests/unit/src/com/android/tv/util/MultiLongSparseArrayTest.java
+++ b/tests/unit/src/com/android/tv/util/MultiLongSparseArrayTest.java
@@ -16,10 +16,13 @@
 
 package com.android.tv.util;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
 import android.support.test.filters.SmallTest;
 import android.test.MoreAsserts;
 
-import junit.framework.TestCase;
+import org.junit.Test;
 
 import java.util.Collections;
 
@@ -27,19 +30,21 @@
  * Tests for {@link MultiLongSparseArray}.
  */
 @SmallTest
-public class MultiLongSparseArrayTest extends TestCase {
-
+public class MultiLongSparseArrayTest {
+    @Test
     public void testEmpty() {
         MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
         assertSame(Collections.EMPTY_SET, sparseArray.get(0));
     }
 
+    @Test
     public void testOneElement() {
         MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
         sparseArray.put(0, "foo");
         MoreAsserts.assertContentsInAnyOrder(sparseArray.get(0), "foo");
     }
 
+    @Test
     public void testTwoElements() {
         MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
         sparseArray.put(0, "foo");
@@ -48,6 +53,7 @@
     }
 
 
+    @Test
     public void testClearEmptyCache() {
         MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
         sparseArray.clearEmptyCache();
@@ -59,6 +65,7 @@
         assertEquals(0, sparseArray.getEmptyCacheSize());
     }
 
+    @Test
     public void testMaxEmptyCacheSize() {
         MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
         sparseArray.clearEmptyCache();
@@ -75,6 +82,7 @@
         assertEquals(0, sparseArray.getEmptyCacheSize());
     }
 
+    @Test
     public void testReuseEmptySets() {
         MultiLongSparseArray<String> sparseArray = new MultiLongSparseArray<>();
         sparseArray.clearEmptyCache();
diff --git a/tests/unit/src/com/android/tv/util/ScaledBitmapInfoTest.java b/tests/unit/src/com/android/tv/util/ScaledBitmapInfoTest.java
index 36d25a1..2714e2e 100644
--- a/tests/unit/src/com/android/tv/util/ScaledBitmapInfoTest.java
+++ b/tests/unit/src/com/android/tv/util/ScaledBitmapInfoTest.java
@@ -1,24 +1,29 @@
 package com.android.tv.util;
 
+import static org.junit.Assert.assertEquals;
+
 import android.graphics.Bitmap;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 
 import com.android.tv.util.BitmapUtils.ScaledBitmapInfo;
 
+import org.junit.Test;
+
 /**
  * Tests for {@link ScaledBitmapInfo}.
  */
 @SmallTest
-public class ScaledBitmapInfoTest extends AndroidTestCase {
+public class ScaledBitmapInfoTest {
     private static final Bitmap B80x100 = Bitmap.createBitmap(80, 100, Bitmap.Config.RGB_565);
     private static final Bitmap B960x1440 = Bitmap.createBitmap(960, 1440, Bitmap.Config.RGB_565);
 
+    @Test
     public void testSize_B100x100to50x50() {
         ScaledBitmapInfo actual = BitmapUtils.createScaledBitmapInfo("B80x100", B80x100, 50, 50);
         assertScaledBitmapSize(2, 40, 50, actual);
     }
 
+    @Test
     public void testNeedsToReload_B100x100to50x50() {
         ScaledBitmapInfo actual = BitmapUtils.createScaledBitmapInfo("B80x100", B80x100, 50, 50);
         assertNeedsToReload(false, actual, 25, 25);
@@ -31,6 +36,7 @@
     /**
      * Reproduces <a href="http://b/20488453">b/20488453</a>.
      */
+    @Test
     public void testBug20488453() {
         ScaledBitmapInfo actual = BitmapUtils
                 .createScaledBitmapInfo("B960x1440", B960x1440, 284, 160);
diff --git a/tests/unit/src/com/android/tv/util/TestUtils.java b/tests/unit/src/com/android/tv/util/TestUtils.java
index e3bda13..d200733 100644
--- a/tests/unit/src/com/android/tv/util/TestUtils.java
+++ b/tests/unit/src/com/android/tv/util/TestUtils.java
@@ -21,8 +21,8 @@
 import android.graphics.drawable.Icon;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.media.tv.TvInputInfo;
+import android.os.Build;
 import android.os.Bundle;
-import android.support.v4.os.BuildCompat;
 
 import java.lang.reflect.Constructor;
 
@@ -47,7 +47,11 @@
             int type, boolean isHardwareInput, boolean canRecord, int tunerCount) throws Exception {
         // Create a mock TvInputInfo by using private constructor
         // Note that mockito doesn't support mock/spy on final object.
-        if (BuildCompat.isAtLeastN()) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            return createTvInputInfoForO(service, id, parentId, type, isHardwareInput, canRecord,
+                    tunerCount);
+
+        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
             return createTvInputInfoForNyc(service, id, parentId, type, isHardwareInput, canRecord,
                     tunerCount);
         }
@@ -57,6 +61,24 @@
     /**
      * private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
      *      CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
+     *      String setupActivity, boolean canRecord, int tunerCount, HdmiDeviceInfo hdmiDeviceInfo,
+     *      boolean isConnectedToHdmiSwitch, String parentId, Bundle extras) {
+     */
+    private static TvInputInfo createTvInputInfoForO(ResolveInfo service, String id,
+            String parentId, int type, boolean isHardwareInput, boolean canRecord, int tunerCount)
+            throws Exception {
+        Constructor<TvInputInfo> constructor = TvInputInfo.class.getDeclaredConstructor(
+                ResolveInfo.class, String.class, int.class, boolean.class, CharSequence.class,
+                int.class, Icon.class, Icon.class, Icon.class, String.class, boolean.class,
+                int.class, HdmiDeviceInfo.class, boolean.class, String.class, Bundle.class);
+        constructor.setAccessible(true);
+        return constructor.newInstance(service, id, type, isHardwareInput, null, 0, null, null,
+                null, null, canRecord, tunerCount, null, false, parentId, null);
+    }
+
+    /**
+     * private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
+     *      CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
      *      String setupActivity, String settingsActivity, boolean canRecord, int tunerCount,
      *      HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch, String parentId,
      *      Bundle extras) {
@@ -87,6 +109,7 @@
         resolveInfo.serviceInfo = new ServiceInfo();
         resolveInfo.serviceInfo.packageName = packageName;
         resolveInfo.serviceInfo.name = name;
+        resolveInfo.serviceInfo.metaData = new Bundle();
         return resolveInfo;
     }
 }
diff --git a/tests/unit/src/com/android/tv/util/TvInputManagerHelperTest.java b/tests/unit/src/com/android/tv/util/TvInputManagerHelperTest.java
index ba1e0b0..404ee5d 100644
--- a/tests/unit/src/com/android/tv/util/TvInputManagerHelperTest.java
+++ b/tests/unit/src/com/android/tv/util/TvInputManagerHelperTest.java
@@ -16,58 +16,155 @@
 
 package com.android.tv.util;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+
 import android.content.pm.ResolveInfo;
 import android.media.tv.TvInputInfo;
 import android.support.test.filters.SmallTest;
-import android.support.test.filters.Suppress;
-import android.test.AndroidTestCase;
 
 import com.android.tv.testing.ComparatorTester;
 
+import org.junit.Test;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
 
-import java.util.LinkedHashMap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 
 /**
  * Test for {@link TvInputManagerHelper}
  */
 @SmallTest
-public class TvInputManagerHelperTest extends AndroidTestCase {
-    public void testComparator() throws Exception {
-        final LinkedHashMap<String, Boolean> INPUT_ID_TO_PARTNER_INPUT = new LinkedHashMap<>();
-        INPUT_ID_TO_PARTNER_INPUT.put("2_partner_input", true);
-        INPUT_ID_TO_PARTNER_INPUT.put("3_partner_input", true);
-        INPUT_ID_TO_PARTNER_INPUT.put("1_3rd_party_input", false);
-        INPUT_ID_TO_PARTNER_INPUT.put("4_3rd_party_input", false);
+public class TvInputManagerHelperTest {
+    final HashMap<String, TvInputInfoWrapper> TEST_INPUT_MAP = new HashMap<>();
 
+    @Test
+    public void testComparatorInternal() {
+        ResolveInfo resolveInfo = TestUtils.createResolveInfo("test", "test");
+
+        List<TvInputInfo> inputs = new ArrayList<>();
+        inputs.add(createTvInputInfo(resolveInfo, "2_partner_input", null, 0, false,
+                "2_partner_input", null, true));
+        inputs.add(createTvInputInfo(resolveInfo, "3_partner_input", null, 0, false,
+                "3_partner_input", null, true));
+        inputs.add(createTvInputInfo(resolveInfo, "1_3rd_party_input", null, 0, false,
+                "1_3rd_party_input", null, false));
+        inputs.add(createTvInputInfo(resolveInfo, "4_3rd_party_input", null, 0, false,
+                "4_3rd_party_input", null, false));
+
+        TvInputManagerHelper manager = createMockTvInputManager();
+
+        ComparatorTester<TvInputInfo> comparatorTester = ComparatorTester.withoutEqualsTest(
+                        new TvInputManagerHelper.InputComparatorInternal(manager));
+        for (TvInputInfo input : inputs) {
+            comparatorTester.addComparableGroup(input);
+        }
+        comparatorTester.test();
+    }
+
+    @Test
+    public void testHardwareInputComparatorHdmi() {
+        ResolveInfo resolveInfo = TestUtils.createResolveInfo("test", "test");
+
+        TvInputInfo hdmi1 = createTvInputInfo(resolveInfo, "HDMI1", null, TvInputInfo.TYPE_HDMI,
+                true, "HDMI1", null, false);
+        TvInputInfo hdmi2 = createTvInputInfo(resolveInfo, "HDMI2", null, TvInputInfo.TYPE_HDMI,
+                true, "HDMI2", "DVD", false);
+        TvInputInfo hdmi3 = createTvInputInfo(resolveInfo, "HDMI3", null, TvInputInfo.TYPE_HDMI,
+                true, "HDMI3", "Cable", false);
+        TvInputInfo hdmi4 = createTvInputInfo(resolveInfo, "HDMI4", null, TvInputInfo.TYPE_HDMI,
+                true, "HDMI4", null, false);
+
+        TvInputManagerHelper manager = createMockTvInputManager();
+
+        ComparatorTester<TvInputInfo> comparatorTester = ComparatorTester.withoutEqualsTest(
+                        new TvInputManagerHelper.HardwareInputComparator(getContext(), manager));
+        comparatorTester.addComparableGroup(hdmi3)
+                .addComparableGroup(hdmi2)
+                .addComparableGroup(hdmi1)
+                .addComparableGroup(hdmi4)
+                .test();
+    }
+
+    @Test
+    public void testHardwareInputComparatorCec() {
+        ResolveInfo resolveInfo = TestUtils.createResolveInfo("test", "test");
+
+        TvInputInfo hdmi1 = createTvInputInfo(resolveInfo, "HDMI1", null, TvInputInfo.TYPE_HDMI,
+                true, "HDMI1", null, false);
+        TvInputInfo hdmi2 = createTvInputInfo(resolveInfo, "HDMI2", null, TvInputInfo.TYPE_HDMI,
+                true, "HDMI2", null, false);
+
+        TvInputInfo cec1 = createTvInputInfo(resolveInfo, "2_cec", "HDMI1", TvInputInfo.TYPE_HDMI,
+                true, "2_cec", null, false);
+        TvInputInfo cec2 = createTvInputInfo(resolveInfo, "1_cec", "HDMI2", TvInputInfo.TYPE_HDMI,
+                true, "1_cec", null, false);
+
+        TvInputManagerHelper manager = createMockTvInputManager();
+
+        ComparatorTester<TvInputInfo> comparatorTester = ComparatorTester.withoutEqualsTest(
+                        new TvInputManagerHelper.HardwareInputComparator(getContext(), manager));
+        comparatorTester.addComparableGroup(cec1)
+                .addComparableGroup(cec2)
+                .test();
+    }
+
+    private TvInputManagerHelper createMockTvInputManager() {
         TvInputManagerHelper manager = Mockito.mock(TvInputManagerHelper.class);
         Mockito.doAnswer(new Answer<Boolean>() {
             @Override
             public Boolean answer(InvocationOnMock invocation) throws Throwable {
                 TvInputInfo info = (TvInputInfo) invocation.getArguments()[0];
-                return INPUT_ID_TO_PARTNER_INPUT.get(info.getId());
+                return TEST_INPUT_MAP.get(info.getId()).mIsPartnerInput;
             }
         }).when(manager).isPartnerInput(Mockito.<TvInputInfo>any());
         Mockito.doAnswer(new Answer<String>() {
             @Override
             public String answer(InvocationOnMock invocation) throws Throwable {
                 TvInputInfo info = (TvInputInfo) invocation.getArguments()[0];
-                return info.getId();
+                return TEST_INPUT_MAP.get(info.getId()).mLabel;
             }
         }).when(manager).loadLabel(Mockito.<TvInputInfo>any());
+        Mockito.doAnswer(new Answer<String>() {
+            @Override
+            public String answer(InvocationOnMock invocation) throws Throwable {
+                TvInputInfo info = (TvInputInfo) invocation.getArguments()[0];
+                return TEST_INPUT_MAP.get(info.getId()).mCustomLabel;
+            }
+        }).when(manager).loadCustomLabel(Mockito.<TvInputInfo>any());
+        Mockito.doAnswer(new Answer<TvInputInfo>() {
+            @Override
+            public TvInputInfo answer(InvocationOnMock invocation) throws Throwable {
+                String inputId = (String) invocation.getArguments()[0];
+                TvInputInfoWrapper inputWrapper = TEST_INPUT_MAP.get(inputId);
+                return inputWrapper == null ? null : inputWrapper.mInput;
+            }
+        }).when(manager).getTvInputInfo(Mockito.<String>any());
+        return manager;
+    }
 
-        ComparatorTester<TvInputInfo> comparatorTester =
-                ComparatorTester.withoutEqualsTest(
-                        new TvInputManagerHelper.TvInputInfoComparator(manager));
-        ResolveInfo resolveInfo1 = TestUtils.createResolveInfo("1_test", "1_test");
-        ResolveInfo resolveInfo2 = TestUtils.createResolveInfo("2_test", "2_test");
-        for (String inputId : INPUT_ID_TO_PARTNER_INPUT.keySet()) {
-            TvInputInfo info1 = TestUtils.createTvInputInfo(resolveInfo1, inputId, null, 0, false);
-            TvInputInfo info2 = TestUtils.createTvInputInfo(resolveInfo2, inputId, null, 0, false);
-            comparatorTester.addComparableGroup(info1, info2);
+    private TvInputInfo createTvInputInfo(ResolveInfo service, String id,
+            String parentId, int type, boolean isHardwareInput, String label, String customLabel,
+            boolean isPartnerInput) {
+        TvInputInfoWrapper inputWrapper = new TvInputInfoWrapper();
+        try {
+            inputWrapper.mInput =
+                    TestUtils.createTvInputInfo(service, id, parentId, type, isHardwareInput);
+        } catch (Exception e) {
         }
-        comparatorTester.test();
+        inputWrapper.mLabel = label;
+        inputWrapper.mIsPartnerInput = isPartnerInput;
+        inputWrapper.mCustomLabel = customLabel;
+        TEST_INPUT_MAP.put(id, inputWrapper);
+        return inputWrapper.mInput;
+    }
+
+    private static class TvInputInfoWrapper {
+        TvInputInfo mInput;
+        String mLabel;
+        String mCustomLabel;
+        boolean mIsPartnerInput;
     }
 }
diff --git a/tests/unit/src/com/android/tv/util/TvTrackInfoUtilsTest.java b/tests/unit/src/com/android/tv/util/TvTrackInfoUtilsTest.java
index 9600fc0..4512bb7 100644
--- a/tests/unit/src/com/android/tv/util/TvTrackInfoUtilsTest.java
+++ b/tests/unit/src/com/android/tv/util/TvTrackInfoUtilsTest.java
@@ -16,13 +16,14 @@
 package com.android.tv.util;
 
 import static com.android.tv.util.TvTrackInfoUtils.getBestTrackInfo;
+import static org.junit.Assert.assertEquals;
 
 import android.media.tv.TvTrackInfo;
 import android.support.test.filters.SmallTest;
 
 import com.android.tv.testing.ComparatorTester;
 
-import junit.framework.TestCase;
+import org.junit.Test;
 
 import java.util.Arrays;
 import java.util.Collections;
@@ -33,8 +34,7 @@
  * Tests for {@link com.android.tv.util.TvTrackInfoUtils}.
  */
 @SmallTest
-public class TvTrackInfoUtilsTest extends TestCase {
-
+public class TvTrackInfoUtilsTest {
     private static final String UN_MATCHED_ID = "no matching ID";
 
     private static final TvTrackInfo INFO_1_EN_1 = create("1", "en", 1);
@@ -59,46 +59,55 @@
     private static final List<TvTrackInfo> NULL_LANGUAGE_TRACKS = Arrays.asList(INFO_4_NULL_2,
             INFO_5_NULL_6);
 
+    @Test
     public void testGetBestTrackInfo_empty() {
         TvTrackInfo result = getBestTrackInfo(Collections.emptyList(), UN_MATCHED_ID, "en", 1);
         assertEquals("best track ", null, result);
     }
 
+    @Test
     public void testGetBestTrackInfo_exactMatch() {
         TvTrackInfo result = getBestTrackInfo(ALL, "1", "en", 1);
         assertEquals("best track ", INFO_1_EN_1, result);
     }
 
+    @Test
     public void testGetBestTrackInfo_langAndChannelCountMatch() {
         TvTrackInfo result = getBestTrackInfo(ALL, UN_MATCHED_ID, "en", 5);
         assertEquals("best track ", INFO_2_EN_5, result);
     }
 
+    @Test
     public void testGetBestTrackInfo_languageOnlyMatch() {
         TvTrackInfo result = getBestTrackInfo(ALL, UN_MATCHED_ID, "fr", 1);
         assertEquals("best track ", INFO_3_FR_8, result);
     }
 
+    @Test
     public void testGetBestTrackInfo_channelCountOnlyMatchWithNullLanguage() {
         TvTrackInfo result = getBestTrackInfo(ALL, UN_MATCHED_ID, null, 8);
         assertEquals("best track ", INFO_3_FR_8, result);
     }
 
+    @Test
     public void testGetBestTrackInfo_noMatches() {
         TvTrackInfo result = getBestTrackInfo(ALL, UN_MATCHED_ID, "kr", 1);
         assertEquals("best track ", INFO_1_EN_1, result);
     }
 
+    @Test
     public void testGetBestTrackInfo_noMatchesWithNullLanguage() {
         TvTrackInfo result = getBestTrackInfo(ALL, UN_MATCHED_ID, null, 0);
         assertEquals("best track ", INFO_1_EN_1, result);
     }
 
+    @Test
     public void testGetBestTrackInfo_channelCountAndIdMatch() {
         TvTrackInfo result = getBestTrackInfo(NULL_LANGUAGE_TRACKS, "5", null, 6);
         assertEquals("best track ", INFO_5_NULL_6, result);
     }
 
+    @Test
     public void testComparator() {
         Comparator<TvTrackInfo> comparator = TvTrackInfoUtils.createComparator("1", "en", 1);
         ComparatorTester.withoutEqualsTest(comparator)
diff --git a/tests/unit/src/com/android/tv/util/UtilsTest_GetDurationString.java b/tests/unit/src/com/android/tv/util/UtilsTest_GetDurationString.java
index 9dfb992..e61802f 100644
--- a/tests/unit/src/com/android/tv/util/UtilsTest_GetDurationString.java
+++ b/tests/unit/src/com/android/tv/util/UtilsTest_GetDurationString.java
@@ -15,10 +15,16 @@
  */
 package com.android.tv.util;
 
+import static android.support.test.InstrumentationRegistry.getContext;
+import static org.junit.Assert.assertEquals;
+
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
 import android.text.format.DateUtils;
 
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
 import java.util.Calendar;
 import java.util.GregorianCalendar;
 import java.util.Locale;
@@ -32,7 +38,7 @@
  * and it should be defined in TV app, not this test.
  */
 @SmallTest
-public class UtilsTest_GetDurationString extends AndroidTestCase {
+public class UtilsTest_GetDurationString {
     // TODO: Mock Context so we can specify current time and locale for test.
     private Locale mLocale;
     private static final long DATE_THIS_YEAR_2_1_MS = getFebOfThisYearInMillis(1, 0, 0);
@@ -40,14 +46,19 @@
     // All possible list for a parameter to test parameter independent result.
     private static final boolean[] PARAM_USE_SHORT_FORMAT = {false, true};
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @Before
+    public void setUp() {
         // Set locale to US
         mLocale = Locale.getDefault();
         Locale.setDefault(Locale.US);
     }
 
+    @After
+    public void tearDown() {
+        // Revive system locale.
+        Locale.setDefault(mLocale);
+    }
+
     /**
      * Return time in millis assuming that whose year is this year and month is Jan.
      */
@@ -76,6 +87,7 @@
         return new GregorianCalendar().get(GregorianCalendar.YEAR);
     }
 
+    @Test
     public void testSameDateAndTime() {
         assertEquals("3:00 AM", Utils.getDurationString(getContext(), DATE_THIS_YEAR_2_1_MS,
                         getFebOfThisYearInMillis(1, 3), getFebOfThisYearInMillis(1, 3), false,
@@ -85,6 +97,7 @@
                         DateUtils.FORMAT_24HOUR));
     }
 
+    @Test
     public void testDurationWithinToday() {
         assertEquals("12:00 – 3:00 AM",
                 Utils.getDurationString(getContext(), DATE_THIS_YEAR_2_1_MS, DATE_THIS_YEAR_2_1_MS,
@@ -96,6 +109,7 @@
                         DateUtils.FORMAT_24HOUR));
     }
 
+    @Test
     public void testDurationFromYesterdayToToday() {
         assertEquals("Jan 31, 3:00 AM – Feb 1, 4:00 AM",
                 Utils.getDurationString(getContext(), DATE_THIS_YEAR_2_1_MS,
@@ -115,6 +129,7 @@
                         true, DateUtils.FORMAT_24HOUR));
     }
 
+    @Test
     public void testDurationFromTodayToTomorrow() {
         assertEquals("Feb 1, 3:00 AM – Feb 2, 4:00 AM",
                 Utils.getDurationString(getContext(), DATE_THIS_YEAR_2_1_MS,
@@ -154,6 +169,7 @@
                         DateUtils.FORMAT_24HOUR));
     }
 
+    @Test
     public void testDurationWithinTomorrow() {
         assertEquals("Feb 2, 2:00 – 4:00 AM",
                 Utils.getDurationString(getContext(), DATE_THIS_YEAR_2_1_MS,
@@ -173,6 +189,7 @@
                         DateUtils.FORMAT_24HOUR));
     }
 
+    @Test
     public void testStartOfDay() {
         assertEquals("12:00 – 1:00 AM",
                 Utils.getDurationString(getContext(), DATE_THIS_YEAR_2_1_MS, DATE_THIS_YEAR_2_1_MS,
@@ -201,6 +218,7 @@
                         DateUtils.FORMAT_24HOUR));
     }
 
+    @Test
     public void testEndOfDay() {
         for (boolean useShortFormat : PARAM_USE_SHORT_FORMAT) {
             assertEquals("11:00 PM – 12:00 AM",
@@ -241,6 +259,7 @@
                         DateUtils.FORMAT_24HOUR));
     }
 
+    @Test
     public void testMidnight() {
         for (boolean useShortFormat : PARAM_USE_SHORT_FORMAT) {
             assertEquals("12:00 AM", Utils.getDurationString(getContext(), DATE_THIS_YEAR_2_1_MS,
@@ -251,11 +270,4 @@
                             DateUtils.FORMAT_24HOUR));
         }
     }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        // Revive system locale.
-        Locale.setDefault(mLocale);
-    }
 }
diff --git a/tests/unit/src/com/android/tv/util/UtilsTest_GetMultiAudioString.java b/tests/unit/src/com/android/tv/util/UtilsTest_GetMultiAudioString.java
index 8a6f3e3..1e75342 100644
--- a/tests/unit/src/com/android/tv/util/UtilsTest_GetMultiAudioString.java
+++ b/tests/unit/src/com/android/tv/util/UtilsTest_GetMultiAudioString.java
@@ -16,21 +16,26 @@
 
 package com.android.tv.util;
 
+import static android.support.test.InstrumentationRegistry.getTargetContext;
+import static org.junit.Assert.assertEquals;
+
 import android.content.Context;
 import android.media.tv.TvTrackInfo;
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
+
+import org.junit.Test;
 
 /**
  * Tests for {@link com.android.tv.util.Utils#getMultiAudioString}.
  */
 @SmallTest
-public class UtilsTest_GetMultiAudioString extends AndroidTestCase {
+public class UtilsTest_GetMultiAudioString {
     private static final String TRACK_ID = "test_track_id";
     private static final int AUDIO_SAMPLE_RATE = 48000;
 
+    @Test
     public void testAudioTrackLanguage() {
-        Context context = getContext();
+        Context context = getTargetContext();
         assertEquals("Korean",
                 Utils.getMultiAudioString(context, createAudioTrackInfo("kor"), false));
         assertEquals("English",
@@ -42,8 +47,9 @@
         assertEquals("abc", Utils.getMultiAudioString(context, createAudioTrackInfo("abc"), false));
     }
 
+    @Test
     public void testAudioTrackCount() {
-        Context context = getContext();
+        Context context = getTargetContext();
         assertEquals("English",
                 Utils.getMultiAudioString(context, createAudioTrackInfo("eng", -1), false));
         assertEquals("English",
@@ -66,11 +72,14 @@
                 Utils.getMultiAudioString(context, createAudioTrackInfo("eng", 8), false));
     }
 
+    @Test
     public void testShowSampleRate() {
         assertEquals("Korean (48kHz)",
-                Utils.getMultiAudioString(getContext(), createAudioTrackInfo("kor", 0), true));
+                Utils.getMultiAudioString(getTargetContext(),
+                createAudioTrackInfo("kor", 0), true));
         assertEquals("Korean (7.1 surround, 48kHz)",
-                Utils.getMultiAudioString(getContext(), createAudioTrackInfo("kor", 8), true));
+                Utils.getMultiAudioString(getTargetContext(),
+                createAudioTrackInfo("kor", 8), true));
     }
 
     private static TvTrackInfo createAudioTrackInfo(String language) {
diff --git a/tests/unit/src/com/android/tv/util/UtilsTest_IsInGivenDay.java b/tests/unit/src/com/android/tv/util/UtilsTest_IsInGivenDay.java
index 926deb0..2b43abc 100644
--- a/tests/unit/src/com/android/tv/util/UtilsTest_IsInGivenDay.java
+++ b/tests/unit/src/com/android/tv/util/UtilsTest_IsInGivenDay.java
@@ -16,8 +16,12 @@
 
 package com.android.tv.util;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
 import android.support.test.filters.SmallTest;
-import android.test.AndroidTestCase;
+
+import org.junit.Test;
 
 import java.util.Calendar;
 import java.util.GregorianCalendar;
@@ -27,19 +31,22 @@
  * Tests for {@link com.android.tv.util.Utils#isInGivenDay}.
  */
 @SmallTest
-public class UtilsTest_IsInGivenDay extends AndroidTestCase {
+public class UtilsTest_IsInGivenDay {
+    @Test
     public void testIsInGivenDay() {
         assertTrue(Utils.isInGivenDay(
                 new GregorianCalendar(2015, Calendar.JANUARY, 1).getTimeInMillis(),
                 new GregorianCalendar(2015, Calendar.JANUARY, 1, 0, 30).getTimeInMillis()));
     }
 
+    @Test
     public void testIsNotInGivenDay() {
         assertFalse(Utils.isInGivenDay(
                 new GregorianCalendar(2015, Calendar.JANUARY, 1).getTimeInMillis(),
                 new GregorianCalendar(2015, Calendar.JANUARY, 2).getTimeInMillis()));
     }
 
+    @Test
     public void testIfTimeZoneApplied() {
         TimeZone timeZone = TimeZone.getDefault();
 
diff --git a/usbtuner-res/animator/setup_before_entry.xml b/usbtuner-res/animator/setup_before_entry.xml
deleted file mode 100644
index 82ed799..0000000
--- a/usbtuner-res/animator/setup_before_entry.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:ordering="together" >
-    <objectAnimator
-        android:duration="@android:integer/config_longAnimTime"
-        android:propertyName="translationX"
-        android:valueFrom="@dimen/ut_guidedstep_entry_slide_from"
-        android:valueTo="@dimen/ut_guidedstep_entry_slide_from"
-        android:valueType="floatType" />
-
-    <objectAnimator
-        android:duration="@android:integer/config_longAnimTime"
-        android:propertyName="alpha"
-        android:valueFrom="0.0"
-        android:valueTo="0.0"
-        android:valueType="floatType" />
-</set>
diff --git a/usbtuner-res/animator/setup_before_exit.xml b/usbtuner-res/animator/setup_before_exit.xml
deleted file mode 100644
index 5c00064..0000000
--- a/usbtuner-res/animator/setup_before_exit.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:ordering="together" >
-
-    <objectAnimator
-        android:duration="@android:integer/config_longAnimTime"
-        android:propertyName="translationX"
-        android:valueFrom="0.0"
-        android:valueTo="0.0"
-        android:valueType="floatType" />
-
-    <objectAnimator
-        android:duration="@android:integer/config_longAnimTime"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="1.0"
-        android:valueType="floatType" />
-
-</set>
diff --git a/usbtuner-res/animator/setup_entry.xml b/usbtuner-res/animator/setup_entry.xml
deleted file mode 100644
index 35fcd4a..0000000
--- a/usbtuner-res/animator/setup_entry.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@android:interpolator/linear_out_slow_in"
-    android:ordering="together" >
-
-    <objectAnimator
-        android:duration="@integer/ut_entry_anim_duration"
-        android:propertyName="translationX"
-        android:valueFrom="@dimen/ut_guidedstep_entry_slide_from"
-        android:valueTo="0.0"
-        android:valueType="floatType" />
-
-    <objectAnimator
-        android:duration="@integer/ut_entry_anim_duration"
-        android:propertyName="alpha"
-        android:valueFrom="0.0"
-        android:valueTo="1.0"
-        android:valueType="floatType" />
-
-</set>
diff --git a/usbtuner-res/animator/setup_exit.xml b/usbtuner-res/animator/setup_exit.xml
deleted file mode 100644
index 4ce89cd..0000000
--- a/usbtuner-res/animator/setup_exit.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:interpolator="@android:interpolator/fast_out_linear_in"
-    android:ordering="together" >
-
-    <objectAnimator
-        android:duration="@integer/ut_exit_anim_duration"
-        android:propertyName="translationX"
-        android:valueFrom="0.0"
-        android:valueTo="@dimen/ut_guidedstep_exit_slide_to"
-        android:valueType="floatType" />
-
-    <objectAnimator
-        android:duration="@integer/ut_exit_anim_duration"
-        android:propertyName="alpha"
-        android:valueFrom="1.0"
-        android:valueTo="0.0"
-        android:valueType="floatType" />
-
-</set>
diff --git a/usbtuner-res/drawable-xhdpi/ic_setup_antenna.png b/usbtuner-res/drawable-xhdpi/ic_setup_antenna.png
deleted file mode 100644
index bb6d416..0000000
--- a/usbtuner-res/drawable-xhdpi/ic_setup_antenna.png
+++ /dev/null
Binary files differ
diff --git a/usbtuner-res/drawable/ut_selector_background.xml b/usbtuner-res/drawable/ut_selector_background.xml
deleted file mode 100644
index fb3899a..0000000
--- a/usbtuner-res/drawable/ut_selector_background.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
-    android:enterFadeDuration="@android:integer/config_shortAnimTime"
-    android:exitFadeDuration="@android:integer/config_shortAnimTime"
-    android:color="?android:attr/colorControlHighlight">
-    <item android:id="@android:id/mask">
-        <shape android:shape="rectangle" >
-            <solid android:color="@android:color/white" />
-            <corners android:radius="2dp" />
-        </shape>
-    </item>
-</ripple>
diff --git a/usbtuner-res/layout/ut_activity_playback.xml b/usbtuner-res/layout/ut_activity_playback.xml
deleted file mode 100644
index b640e6d..0000000
--- a/usbtuner-res/layout/ut_activity_playback.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:keepScreenOn="true"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:orientation="vertical" >
-
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-    <SurfaceView
-        android:id="@+id/surface1"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-</LinearLayout>
diff --git a/usbtuner-res/layout/ut_guidance.xml b/usbtuner-res/layout/ut_guidance.xml
deleted file mode 100644
index 4f7d3f7..0000000
--- a/usbtuner-res/layout/ut_guidance.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@null"
-    android:paddingStart="@dimen/ut_guidance_padding_start"
-    android:paddingEnd="@dimen/ut_guidance_padding_end"
-    android:paddingTop="@dimen/ut_guidance_padding_top"
-    android:clipToPadding="false"
-    android:clipChildren="false" >
-    <ImageView
-        android:id="@+id/guidance_icon"
-        android:visibility="gone"
-        style="?attr/guidanceIconStyle"
-        tools:ignore="ContentDescription" />
-    <RelativeLayout
-        style="?attr/guidanceContainerStyle" >
-        <Space
-            android:id="@+id/guidance_anchor_space"
-            style="@style/ut_guidance_anchor" />
-        <TextView
-            android:id="@+id/guidance_title"
-            style="?attr/guidanceTitleStyle" />
-        <TextView
-            android:id="@+id/guidance_breadcrumb"
-            style="?attr/guidanceBreadcrumbStyle" />
-        <TextView
-            android:id="@+id/guidance_description"
-            style="?attr/guidanceDescriptionStyle" />
-    </RelativeLayout>
-</FrameLayout>
diff --git a/usbtuner-res/layout/ut_guidedactions.xml b/usbtuner-res/layout/ut_guidedactions.xml
deleted file mode 100644
index ae7efc0..0000000
--- a/usbtuner-res/layout/ut_guidedactions.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<!-- Layout for the settings list fragment -->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@null"
-    android:paddingStart="@dimen/ut_guidedactions_padding_start"
-    android:paddingEnd="@dimen/ut_guidedactions_padding_end"
-    android:paddingTop="@dimen/ut_guidedactions_padding_top"
-    android:paddingBottom="@dimen/ut_guidedactions_padding_bottom"
-    android:clipToPadding="false"
-    android:clipChildren="false" >
-    <RelativeLayout
-        style="?attr/guidedActionsContainerStyle" >
-        <Space
-            android:id="@+id/guidedactions_anchor_space"
-            style="@style/ut_guidedactions_anchor" />
-        <FrameLayout
-            android:id="@+id/guidedactions_selector"
-            style="@style/ut_guidedactions_null_selector" />
-        <android.support.v17.leanback.widget.VerticalGridView
-            android:id="@+id/guidedactions_list"
-            style="?attr/guidedActionsListStyle" />
-    </RelativeLayout>
-</FrameLayout>
\ No newline at end of file
diff --git a/usbtuner-res/raw/ut_euro_dvbt_all b/usbtuner-res/raw/ut_euro_dvbt_all
new file mode 100644
index 0000000..101ee3e
--- /dev/null
+++ b/usbtuner-res/raw/ut_euro_dvbt_all
@@ -0,0 +1,287 @@
+# Euro DVB-T frequencies
+# Only Germany and England frequencies are added now.
+
+# Frequencies from Germany
+T 474000000 QAM16
+T 474000000 QAM64
+T 482000000 QAM16
+T 490000000 QAM16
+T 498000000 QAM16
+T 498000000 QAM64
+T 506000000 QAM16
+T 506000000 QAM64
+T 514000000 QAM16
+T 522000000 QAM16
+T 522000000 QAM64
+T 530000000 QAM16
+T 538000000 QAM16
+T 538000000 QAM64
+T 546000000 QAM16
+T 554000000 QAM16
+T 554000000 QAM64
+T 562000000 QAM16
+T 562000000 QAM64
+T 570000000 QAM16
+T 578000000 QAM16
+T 578000000 QAM64
+T 586000000 QAM16
+T 594000000 QAM16
+T 602000000 QAM16
+T 602000000 QAM64
+T 610000000 QAM16
+T 610000000 QAM64
+T 618000000 QAM16
+T 618000000 QAM64
+T 626000000 QAM16
+T 634000000 QAM16
+T 634000000 QAM64
+T 642000000 QAM16
+T 650000000 QAM16
+T 658000000 QAM16
+T 666000000 QAM16
+T 674000000 QAM16
+T 674000000 QAM64
+T 682000000 QAM16
+T 690000000 QAM16
+T 690000000 QAM64
+T 698000000 QAM16
+T 698000000 QAM64
+T 706000000 QAM16
+T 722000000 QAM16
+T 730000000 QAM16
+T 730000000 QAM64
+T 738000000 QAM16
+T 738000000 QAM64
+T 746000000 QAM16
+T 746000000 QPSK
+T 754000000 QAM16
+T 762000000 QAM16
+T 770000000 QAM16
+T 778000000 QAM16
+T 786000000 QAM16
+
+# Frequencies from England
+T 474000000 QAM16
+T 474000000 QAM64
+T 474167000 QAM16
+T 474167000 QAM64
+T 481833000 QAM16
+T 481833000 QAM64
+T 481833330 QAM64
+T 482000000 QAM16
+T 482167000 QAM16
+T 482167000 QAM64
+T 489833000 QAM16
+T 489833000 QAM64
+T 490000000 QAM16
+T 490000000 QAM64
+T 490167000 QAM16
+T 490167000 QAM64
+T 497833000 QAM16
+T 497833000 QAM64
+T 498000000 QAM16
+T 498000000 QAM64
+T 498167000 QAM16
+T 498167000 QAM64
+T 505833000 QAM16
+T 505833000 QAM64
+T 505833330 QAM16
+T 506000000 QAM16
+T 506000000 QAM64
+T 506167000 QAM16
+T 506167000 QAM64
+T 513833000 QAM16
+T 514000000 QAM16
+T 514000000 QAM64
+T 514167000 QAM16
+T 514167000 QAM64
+T 521833000 QAM64
+T 522000000 QAM16
+T 522000000 QAM64
+T 522167000 QAM16
+T 529833000 QAM16
+T 529833000 QAM64
+T 529833330 QAM16
+T 530000000 QAM16
+T 530000000 QAM64
+T 530167000 QAM16
+T 530167000 QAM64
+T 537833000 QAM64
+T 537833330 QAM16
+T 538000000 QAM16
+T 538000000 QAM64
+T 538167000 QAM16
+T 538167000 QAM64
+T 545833000 QAM16
+T 545833000 QAM64
+T 546000000 QAM16
+T 546000000 QAM64
+T 546167000 QAM16
+T 546167000 QAM64
+T 553833000 QAM16
+T 553833000 QAM64
+T 554000000 QAM16
+T 554000000 QAM64
+T 561833000 QAM16
+T 561833000 QAM64
+T 561833330 QAM64
+T 562000000 QAM16
+T 562000000 QAM64
+T 562167000 QAM16
+T 569833000 QAM64
+T 570000000 QAM16
+T 570167000 QAM16
+T 577833000 QAM16
+T 578000000 QAM16
+T 578000000 QAM64
+T 578166670 QAM16
+T 578167000 QAM16
+T 578167000 QAM64
+T 586000000 QAM16
+T 594000000 QAM16
+T 602000000 QAM16
+T 602000000 QAM64
+T 610000000 QAM16
+T 610000000 QAM64
+T 618000000 QAM16
+T 618000000 QAM64
+T 618167000 QAM16
+T 625833000 QAM64
+T 626000000 QAM16
+T 626000000 QAM64
+T 626167000 QAM16
+T 626167000 QAM64
+T 633833000 QAM64
+T 634000000 QAM16
+T 634000000 QAM64
+T 634167000 QAM16
+T 634167000 QAM64
+T 641833000 QAM16
+T 642000000 QAM16
+T 642000000 QAM64
+T 642167000 QAM64
+T 649833000 QAM16
+T 650000000 QAM16
+T 650000000 QAM64
+T 650167000 QAM16
+T 650167000 QAM64
+T 657833000 QAM16
+T 657833000 QAM64
+T 658000000 QAM64
+T 658000000 QAM16
+T 658167000 QAM16
+T 658167000 QAM64
+T 665833000 QAM16
+T 665833000 QAM64
+T 666000000 QAM16
+T 666000000 QAM64
+T 666167000 QAM16
+T 673833000 QAM16
+T 674000000 QAM16
+T 674000000 QAM64
+T 674167000 QAM16
+T 681833000 QAM16
+T 682000000 QAM16
+T 682000000 QAM64
+T 682167000 QAM16
+T 682167000 QAM64
+T 689833000 QAM64
+T 690000000 QAM16
+T 690000000 QAM64
+T 690167000 QAM16
+T 690167000 QAM64
+T 697833000 QAM16
+T 698000000 QAM16
+T 698000000 QAM64
+T 698167000 QAM16
+T 705833000 QAM16
+T 706000000 QAM16
+T 706000000 QAM64
+T 706167000 QAM16
+T 706167000 QAM64
+T 713833000 QAM16
+T 713833000 QAM64
+T 714000000 QAM16
+T 714000000 QAM64
+T 714167000 QAM16
+T 714167000 QAM64
+T 721833000 QAM16
+T 722000000 QAM16
+T 722167000 QAM16
+T 722167000 QAM64
+T 729833000 QAM16
+T 729833000 QAM64
+T 730000000 QAM16
+T 730000000 QAM64
+T 730167000 QAM16
+T 737833000 QAM16
+T 738000000 QAM16
+T 738000000 QAM64
+T 738167000 QAM16
+T 738167000 QAM64
+T 745833000 QAM16
+T 745833000 QAM64
+T 746000000 QAM16
+T 746000000 QAM64
+T 746000000 QPSK
+T 746167000 QAM64
+T 753833000 QAM16
+T 753833000 QAM64
+T 754000000 QAM16
+T 754000000 QAM64
+T 754167000 QAM16
+T 761833000 QAM16
+T 761833000 QAM64
+T 762000000 QAM16
+T 762000000 QAM256
+T 762000000 QAM64
+T 762167000 QAM16
+T 762167000 QAM64
+T 769833000 QAM64
+T 770000000 QAM16
+T 770000000 QAM64
+T 770167000 QAM16
+T 770167000 QAM64
+T 777833000 QAM16
+T 777833000 QAM64
+T 778000000 QAM16
+T 778000000 QAM64
+T 778167000 QAM16
+T 778167000 QAM64
+T 785833000 QAM16
+T 785833000 QAM64
+T 786000000 QAM16
+T 786000000 QAM64
+T 786167000 QAM16
+T 786167000 QAM64
+T 793833000 QAM64
+T 794000000 QAM64
+T 794167000 QAM16
+T 794167000 QAM64
+T 801833000 QAM16
+T 801833000 QAM64
+T 802000000 QAM16
+T 802000000 QAM64
+T 802167000 QAM16
+T 802167000 QAM64
+T 809833000 QAM16
+T 810000000 QAM16
+T 810167000 QAM16
+T 817833000 QAM16
+T 818000000 QAM16
+T 818167000 QAM16
+T 825833000 QAM16
+T 825833000 QAM64
+T 826000000 QAM16
+T 826167000 QAM16
+T 826167000 QAM64
+T 833833000 QAM64
+T 834000000 QAM16
+T 834000000 QAM64
+T 834167000 QAM16
+T 834167000 QAM64
+T 842000000 QAM16
+T 842000000 QAM64
+T 842167000 QAM64
+T 850000000 QAM16
+T 850000000 QAM64
\ No newline at end of file
diff --git a/usbtuner-res/raw/ut_kr_all b/usbtuner-res/raw/ut_kr_all
index 8532012..9c4d7e6 100644
--- a/usbtuner-res/raw/ut_kr_all
+++ b/usbtuner-res/raw/ut_kr_all
@@ -1,5 +1,4 @@
 # KR ATSC center frequencies
-# TODO: Verify this.
 
 A 473028615 8VSB
 A 479028615 8VSB
diff --git a/usbtuner-res/raw/ut_kr_atsc_center_frequencies_8vsb b/usbtuner-res/raw/ut_kr_atsc_center_frequencies_8vsb
index 4ddbf0b..14678d3 100644
--- a/usbtuner-res/raw/ut_kr_atsc_center_frequencies_8vsb
+++ b/usbtuner-res/raw/ut_kr_atsc_center_frequencies_8vsb
@@ -1,5 +1,4 @@
 # KR ATSC center frequencies
-# TODO: Verify this.
 
 A 473028615 8VSB
 A 479028615 8VSB
diff --git a/usbtuner-res/raw/ut_us_all b/usbtuner-res/raw/ut_us_all
index f3d2d8f..a5bd846 100644
--- a/usbtuner-res/raw/ut_us_all
+++ b/usbtuner-res/raw/ut_us_all
@@ -1,5 +1,4 @@
 # US ATSC center frequencies
-# TODO: Verify this.
 
 A  57028615 8VSB 2
 A  63028615 8VSB 3
@@ -71,7 +70,6 @@
 A 803028615 8VSB 69
 # US EIA/NCTA Standard Cable center frequencies
 # Channels are in ascending EIA/NCTA channel designation order
-# TODO: Verify this.
 
 #2
 A  57000000 QAM256
diff --git a/usbtuner-res/raw/ut_us_atsc_center_frequencies_8vsb b/usbtuner-res/raw/ut_us_atsc_center_frequencies_8vsb
index bb59e07..245a68a 100644
--- a/usbtuner-res/raw/ut_us_atsc_center_frequencies_8vsb
+++ b/usbtuner-res/raw/ut_us_atsc_center_frequencies_8vsb
@@ -1,5 +1,4 @@
 # US ATSC center frequencies
-# TODO: Verify this.
 
 A  57028615 8VSB 2
 A  63028615 8VSB 3
diff --git a/usbtuner-res/raw/ut_us_cable_standard_center_frequencies_qam256 b/usbtuner-res/raw/ut_us_cable_standard_center_frequencies_qam256
index d2d5e30..f42a514 100644
--- a/usbtuner-res/raw/ut_us_cable_standard_center_frequencies_qam256
+++ b/usbtuner-res/raw/ut_us_cable_standard_center_frequencies_qam256
@@ -1,6 +1,5 @@
 # US EIA/NCTA Standard Cable center frequencies
 # Channels are in ascending EIA/NCTA channel designation order
-# TODO: Verify this.
 
 #2
 A  57000000 QAM256
diff --git a/usbtuner-res/values-af/strings.xml b/usbtuner-res/values-af/strings.xml
index 4337a69..8fd5070 100644
--- a/usbtuner-res/values-af/strings.xml
+++ b/usbtuner-res/values-af/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV-ontvanger"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-TV-ontvanger"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Aan"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Af"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Netwerk-TV-ontvanger (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Wag asseblief dat verwerking voltooi word"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Kies jou kanaalbron"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Geen sein nie"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Kon nie op <xliff:g id="CHANNEL_NAME">%s</xliff:g> inskakel nie"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Kon nie inskakel nie"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Ontvangersagteware is onlangs opgedateer. Herskandeer die kanale asseblief."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Aktiveer omringklank in stelselklankinstellings om oudio te aktiveer"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Kan nie oudio speel nie. Probeer asseblief \'n ander TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Opstelling van kanaalontvanger"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Opstelling van TV-ontvanger"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Opstelling van USB-kanaalontvanger"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Opstelling van netwerkontvanger"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Maak seker dat jou TV aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, sal jy dalk sy plasing of rigting moet verander om die meeste kanale te ontvang. Plaas dit vir die beste resultate hoog en naby \'n venster."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Maak seker dat die USB-ontvanger ingeprop en aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, sal jy dalk sy posisie of rigting moet verander om die meeste kanale te ontvang. Plaas dit vir die beste resultate hoog en naby \'n venster."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Maak seker dat die netwerkontvanger aangeskakel is en aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, sal jy dalk sy plasing of rigting waarin hy wys, moet verstel om die meeste kanale te ontvang. Plaas dit vir die beste resultate hoog en naby \'n venster."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Gaan voort"</item>
     <item msgid="727245208787621142">"Nie nou nie"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Doen kanaalopstelling weer?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Dit sal die kanale wat ontvang is, uit die TV-ontvanger verwyder en weer nuwe kanale soek.\n\nMaak seker dat jou TV aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, sal jy dalk sy plasing of rigting moet verander om die meeste kanale te ontvang. Plaas dit vir die beste resultate hoog en naby \'n venster."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Dit sal die kanale wat gevind is, uit die USB-ontvanger verwyder en weer nuwe kanale soek.\n\nMaak seker dat die USB-ontvanger ingeprop en aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, sal jy dalk sy posisie of rigting moet verander om die meeste kanale te ontvang. Plaas dit vir die beste resultate hoog en naby \'n venster."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Dit sal die kanale wat gevind is van die netwerkontvanger af verwyder en weer na nuwe kanale soek.\n\nMaak seker dat die netwerkontvanger aangeskakel is en aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, sal jy dalk sy plasing of rigting waarin hy wys, moet verstel om die meeste kanale te ontvang. Plaas dit vir die beste resultate hoog en naby \'n venster."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Gaan voort"</item>
     <item msgid="235450158666155406">"Kanselleer"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Opstelling van TV-ontvanger"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Opstelling van USB-kanaalontvanger"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Opstelling van netwerkkanaalontvanger"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Dit kan \'n paar minute neem"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Seinontvanger is tydelik nie beskikbaar nie of word reeds deur opname gebruik."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Geen kanale gevind nie"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Geen kanale is in die soektog gevind nie. Maak seker dat jou TV aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, verander sy plasing of rigting. Plaas dit vir die beste resultate hoog en naby \'n venster en soek weer."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Geen kanale is in die soektog gevind nie. Maak seker dat die USB-ontvanger ingeprop en aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, verander sy posisie of rigting. Plaas dit vir die beste resultate hoog en naby \'n venster en soek weer."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Geen kanale is in die soektog gevind nie. Maak seker dat die netwerkontvanger aangeskakel is en aan \'n TV-seinbron gekoppel is.\n\nAs jy \'n oor-die-lug-antenna gebruik, verstel sy plasing of rigting waarin hy wys. Plaas dit vir die beste resultate hoog en naby \'n venster en soek weer."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Soek weer"</item>
     <item msgid="2092797862490235174">"Klaar"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Soek TV-kanale"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Opstelling van TV-ontvanger"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Opstelling van USB-TV-ontvanger"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-TV-ontvanger is ontkoppel."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Soek TV-kanale"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Opstelling van TV-ontvanger"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Opstelling van USB-TV-ontvanger"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Opstelling van netwerk-TV-ontvanger"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-TV-ontvanger is ontkoppel."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Netwerkontvanger is ontkoppel."</string>
 </resources>
diff --git a/usbtuner-res/values-am/strings.xml b/usbtuner-res/values-am/strings.xml
index a903ee7..cbf1e9f 100644
--- a/usbtuner-res/values-am/strings.xml
+++ b/usbtuner-res/values-am/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"የቴሌቪዥን መቃኛ"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"የዩኤስቢ ቴሌቪዥን መቃኛ"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"በርቷል"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"ጠፍቷል"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"የአውታረ መረብ ቴሌቪዥን መቃኛ (ቅድመ-ይሁንታ)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"ማስኬድን ለማጠናቀቅ እባክዎ ይጠብቁ"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"የጣቢያ ምንጭዎን ይምረጡ"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"ምንም ሲግናል የለም"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"ወደ <xliff:g id="CHANNEL_NAME">%s</xliff:g> መቃኘት አልተሳካም"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"መቃኘት አልተሳካም"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"የቴሌቪዥን መቃኛ ሶፍትዌር በቅርብ ጊዜ ተዘምኗል። እባክዎ ሰርጦቹን እንደገና ይቃኟቸው።"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ኦዲዮን ለማንቃት በስርዓት ድምጽ ቅንብሮች ውስጥ የዙሪያ ድምጽን ያንቁ"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"ኦዲዮ ማጫወት አይቻልም። እባክዎ ሌላ ቲቪ ይሞክሩ።"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"የጣቢያ መቃኛ ማዋቀር"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"የቴሌቪዥን መቃኛ ማዋቀር"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"የዩኤስቢ ጣቢያ መቃኛ ማዋቀር"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"የአውታረ መረብ መቃኛ ማዋቀር"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"የእርስዎ ቴሌቪዥን ከቴሌቪዥን ሲግናል ምልክት ምንጭ ጋር መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና የሚጠቀሙ ከሆነ አብዛኛዎቹን ጣቢያዎች ለመቀበል አቀማመጡን ወይም አቅጣጫውን ማስተካከል ሊኖርብዎት ይችላል። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡት።"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"የዩኤስቢ መቃኛው መሰካቱን እና ከቴሌቪዥን ምልክት ምንጭ ጋር መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና የሚጠቀሙ ከሆነ አቀማመጡን ወይም አቅጣጫውን ያስተካክሉ። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡት።"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"የአውታረ መረብ መቃኛው እና ከቴሌቪዥን ምልክት ምንጭ ጋር መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና የሚጠቀሙ ከሆነ አቀማመጡን ወይም አቅጣጫውን ያስተካክሉ። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡት።"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"ቀጥል"</item>
     <item msgid="727245208787621142">"አሁን አይደለም"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"የጣቢያ ቅንብር እንደገና እንዲሄድ ይደረግ?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"ይሄ ከቴሌቪዥን መቃኛ የተገኙ ጣቢያዎችን አስወግዶ አዲስ ጣቢያዎችን እንደገና ይቃኛል።\n\nየእርስዎ ቴሌቪዥን ከቴሌቪዥን ሲግናል ምልክት ምንጭ ጋር መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና የሚጠቀሙ ከሆነ አብዛኛዎቹን ጣቢያዎች ለመቀበል አቀማመጡን ወይም አቅጣጫውን ማስተካከል ሊኖርብዎት ይችላል። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡት።"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"ይሄ ከዩኤስቢ መቃኛ የተገኙ ጣቢያዎችን አስወግዶ አዲስ ጣቢያዎችን እንደገና ይቃኛል።\n\nየዩኤስቢ መቃኛው መሰካቱን እና ከቴሌቪዥን ምልክት ምንጭ ጋር መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና የሚጠቀሙ ከሆነ አቀማመጡን ወይም አቅጣጫውን ያስተካክሉ። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡት።"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"ይሄ ከአውታረ መረብ መቃኛ የተገኙ ጣቢያዎችን አስወግዶ አዲስ ጣቢያዎችን እንደገና ይቃኛል።\n\nየአውታረ መረብ መቃኛው እና ከቴሌቪዥን ምልክት ምንጩ መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና የሚጠቀሙ ከሆነ አቀማመጡን ወይም አቅጣጫውን ያስተካክሉ። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡት።"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"ቀጥል"</item>
     <item msgid="235450158666155406">"ይቅር"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"የቴሌቪዥን መቃኛ ማዋቀር"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"የዩኤስቢ ጣቢያ መቃኛ ማዋቀር"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"የአውታረ መረብ ጣቢያ መቃኛ ማዋቀር"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"ይሄ በርካታ ደቂቃዎችን ሊወስድ ይችላል"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"መቃኛው ለጊዜው አይገኝም ወይም አስቀድሞ በቀረጻው ጥቅም ላይ ውሏል።"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"ምንም ጣቢያዎች አልተገኙም"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"ቅኝቱ ምንም አዲስ ጣቢያዎችን አላገኘም። የእርስዎ ቴሌቪዥን ከቴሌቪዥን ሲግናል ምንጭ ጋር መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና ከሆነ የሚጠቀሙት አቀማመጡን ወይም አቅጣጫውን ያስተካክሉት። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡትና እንደገና ይቃኙ።"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"ቅኝቱ ምንም ጣቢያዎችን አላገኘም። የዩኤስቢ መቃኛው መሰካቱን እና ከቴሌቪዥን ሲግናል ምንጩ ጋር መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና የሚጠቀሙ ከሆነ አቀማመጡን ወይም አቅጣጫውን ያስተካክሉ። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡት እና እንደገና ይቃኙ።"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"ቅኝቱ ምንም ጣቢያዎችን አላገኘም። የአውታረ መረብ መቃኛው እንደበራ እና ከቴሌቪዥን ሲግናል ምንጩ ጋር መገናኘቱን ያረጋግጡ።\n\nየአየር ላይ አንቴና የሚጠቀሙ ከሆነ አቀማመጡን ወይም አቅጣጫውን ያስተካክሉ። ለተሻሉ ውጤቶች ከፍ አድርገው ከመስኮት አጠገብ ያስቀምጡት እና እንደገና ይቃኙ።"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"እንደገና ቃኝ"</item>
     <item msgid="2092797862490235174">"ተከናውኗል"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"የቲቪ ጣቢያዎችን ቃኝ"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"የቴሌቪዥን መቃኛ ማዋቀር"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"የዩኤስቢ ቴሌቪዥን መቃኛ ማዋቀር"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"የUSB TV መቃኛ ግንኙነቱ ተቋርጧል።"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"የቴሌቪዥን ጣቢያዎችን ቃኝ"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"የቴሌቪዥን መቃኛ ማዋቀር"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"የዩኤስቢ ቴሌቪዥን መቃኛ ማዋቀር"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"የአውታረ መረብ ቴሌቪዥን መቃኛ ማዋቀር"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"የዩኤስቢ ቴሌቪዥን መቃኛው ግንኙነት ተቋርጧል።"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"የአውታረ መረብ መቃኛ ግንኙነት ተቋርጧል።"</string>
 </resources>
diff --git a/usbtuner-res/values-ar/strings.xml b/usbtuner-res/values-ar/strings.xml
index ecfde3e..ae197d1 100644
--- a/usbtuner-res/values-ar/strings.xml
+++ b/usbtuner-res/values-ar/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"موالف التلفزيون"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"‏موالف التلفزيون عبر USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"تشغيل"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"إيقاف"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"موالف التلفزيون على الشبكة (تجريبي)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"الرجاء الانتظار لحين انتهاء المعالجة"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"تحديد مصدر القنوات"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"لا توجد إشارة"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"أخفق الضبط على <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"أخفق الضبط"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"تم تحديث برنامج الموالف مؤخرًا. الرجاء إعادة البحث عن القنوات."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"يمكنك تشغيل الصوت المحيطي في إعدادات صوت النظام لتفعيل الصوت"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"لا يمكن تشغيل الصوت. الرجاء تجربة تلفزيون آخر."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"إعداد موالف القنوات"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"إعداد موالف التلفزيون"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"‏إعداد موالف قنوات USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"إعداد موالف الشبكة"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"تحقق من توصيل التلفزيون بمصدر إشارة البث التلفزيوني.\n\nإذا كنت تستخدم هوائيًا للتحديث عبر الهواء، فقد تحتاج إلى ضبط موضعه أو اتجاهه لاستقبال معظم القنوات، وللحصول على أفضل النتائج، ضعه عاليًا بالقرب من النافذة."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"‏تحقق من توصيل الموالف عبر USB بمصدر إشارة البث التلفزيوني.\n\nإذا كنت تستخدم هوائيًا للتحديث عبر الهواء، فقد تحتاج إلى ضبط موضعه أو اتجاهه لاستقبال معظم القنوات، وللحصول على أفضل النتائج، ضعه عاليًا بالقرب من النافذة."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"تحقق من تشغيل موالف الشبكة وتوصيله بمصدر إشارة التلفزيون.\n\nفي حالة استخدام هوائي للتحديث عبر الهواء، قد تحتاج إلى ضبط موضعه أو تجاهه لاستقبال معظم القنوات. وللحصول على أفضل النتائج، يمكنك وضعه في مكان مرتفع أو بالقرب من النافذة."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"متابعة"</item>
     <item msgid="727245208787621142">"ليس الآن"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"هل تريد إعادة تشغيل إعداد القنوات؟"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"سيؤدي هذا إلى إزالة القنوات التي تم العثور عليها من موالف التلفزيون والبحث مرة أخرى عن قنوات جديدة.\n\nتحقق من توصيل التلفزيون بمصدر إشارة البث التلفزيوني.\n\nإذا كنت تستخدم هوائيًا للتحديث عبر الهواء، فقد تحتاج إلى ضبط موضعه أو اتجاهه لاستقبال معظم القنوات، وللحصول على أفضل النتائج، ضعه عاليًا بالقرب من النافذة."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"‏سيؤدي هذا إلى إزالة القنوات التي تم العثور عليها من الموالف عبر USB والبحث مرة أخرى عن قنوات جديدة.\n\nتحقق من توصيل الموالف عبر USB بمصدر إشارة البث التلفزيوني.\n\nإذا كنت تستخدم هوائيًا للتحديث عبر الهواء، فقد تحتاج إلى ضبط موضعه أو اتجاهه لاستقبال معظم القنوات، وللحصول على أفضل النتائج، ضعه عاليًا بالقرب من النافذة."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"سيؤدي هذا إلى إزالة القنوات الموجودة من موالف الشبكة وإعادة المسح بحثًا عن القنوات الجديدة.\n\nتحقق من تشغيل موالف الشبكة وتوصيله بمصدر إشارة التلفزيون.\n\nفي حالة استخدام هوائي للتحديث عبر الهواء، قد تحتاج إلى ضبط موضعه أو تجاهه لاستقبال معظم القنوات. وللحصول على أفضل النتائج، يمكنك وضعه في مكان مرتفع أو بالقرب من النافذة."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"متابعة"</item>
     <item msgid="235450158666155406">"إلغاء"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"إعداد موالف التلفزيون"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"‏إعداد موالف قنوات USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"إعداد موالف قناة الشبكة"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"قد يستغرق هذا عدة دقائق"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"لا يتوفر الموالف مؤقتًا أو سبق استخدامه بواسطة التسجيل."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -88,12 +88,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"لم يتم العثور على قنوات"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"لم يتم العثور على أي قنوات أثناء البحث، لذا عليك التحقق من توصيل التلفزيون بمصدر إشارة البث التلفزيوني.\n\nإذا كنت تستخدم هوائيًا للتحديث عبر الهواء، فاضبط موضعه أو اتجاهه، وللحصول على أفضل النتائج، ضعه عاليًا بالقرب من النافذة ثم أعد البحث."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"‏لم يتم العثور على أي قنوات أثناء البحث، تحقق من توصيل الموالف عبر USB بمصدر إشارة البث التلفزيوني.\n\nإذا كنت تستخدم هوائيًا للتحديث عبر الهواء، فاضبط موضعه أو اتجاهه، وللحصول على أفضل النتائج، ضعه عاليًا بالقرب من النافذة ثم أعد البحث."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"لم يتم العثور على أي قنوات خلال المسح. تحقق من تشغيل موالف الشبكة وتوصيله بمصدر إشارة التلفزيون.\n\nفي حالة استخدام هوائي للتحديث عبر الهواء، يجب ضبط موضعه أو تجاهه. وللحصول على أفضل النتائج، يمكنك وضعه في مكان مرتفع أو بالقرب من النافذة وإعادة المسح."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"بحث مرة أخرى"</item>
     <item msgid="2092797862490235174">"تم"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"البحث عن قنوات تلفزيونية"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"إعداد موالف التلفزيون"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"‏إعداد موالف التلفزيون عبر USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"‏تم فصل موالف التلفزيون عبر USB."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"البحث عن قنوات تلفزيونية"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"إعداد موالف التلفزيون"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"‏إعداد موالف التلفزيون عبر USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"إعداد موالف التلفزيون على الشبكة"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"‏تم فصل موالف التلفزيون عبر USB."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"تم فصل موالف الشبكة."</string>
 </resources>
diff --git a/usbtuner-res/values-az/strings.xml b/usbtuner-res/values-az-rAZ/strings.xml
similarity index 74%
rename from usbtuner-res/values-az/strings.xml
rename to usbtuner-res/values-az-rAZ/strings.xml
index f530581..2022ad7 100644
--- a/usbtuner-res/values-az/strings.xml
+++ b/usbtuner-res/values-az-rAZ/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV Kökləyici"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV Kökləyici"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Aktiv"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Deaktiv"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Lütfən, prosesi başa çatdırmaq üçün gözləyin"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Kanal mənbəyinizi seçin"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Siqnal Yoxdur"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> kanalına sazlamaq mümkün olmadı"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Sazlamaq uğursuz oldu"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Sazlayıcı proqram təminatı yenicə güncəllənib. Kanalları yenidən skan edin."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Audionu aktiv etmək üçün sistem səs ayarlarında əhatəli səsi aktiv edin"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Audio oxuna bilmir. Digər TV-dən istifadə edin"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kanal kökləyici quraşdırması"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV Kökləyici quraşdırması"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB Kanal kökləyici quraşdırması"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Şəbəkə kökləyici quraşdırması"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"TV-nizin TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB kökləyicinin taxılı olduğunu və TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Şəbəkə kökləyicinin yanılı olduğunu və TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Davam edin"</item>
     <item msgid="727245208787621142">"İndi yox"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Kanal quraşdırması yenidən işə salınsın?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Bu, TV kökləyici ilə tapılmış kanalları siləcək və yeni kanalları yenidən skan edəcək.\n\nTV-nizin TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Bu USB kökləyici ilə tapılmış kanalları siləcək və yeni kanalları yenidən skan edəcək.\n\nUSB kökləyicinin taxılı olduğunu və TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Bu Şəbəkə kökləyici ilə tapılmış kanalları siləcək və yeni kanalları yenidən skan edəcək.\n\nŞəbəkə kökləyicinin yanılı olduğunu və TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Davam edin"</item>
     <item msgid="235450158666155406">"Ləğv edin"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV kökləyici quraşdırması"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB Kanal kökləyici quraşdırması"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Şəbəkə kanalı kökləyici quraşdırması"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Bu bir neçə dəqiqə çəkə bilər"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Kökləyici müvəqqəti əlçatan deyil və qeydə alma tərəfindən istifadə olunub."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Kanal tapılmadı"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Skan ilə heç bir kanal tapılmadı. TV-nizin TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Skan ilə heç bir kanal tapılmadı. USB kökləyicinin taxılı olduğunu və TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Skan ilə heç bir kanal tapılmadı. Şəbəkə kökləyicinin yanılı olduğunu və TV siqnal mənbəyinə qoşulu olduğunu doğrulayın.\n\nHava antenası istifadə etdikdə, daha çox kanal üçün onun yerini və istiqamətini tənzimləməlisiniz. Daha yaxşı nəticələr üçün hündür yerə və pəncərəyə yaxın yerləşdirin."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Yenidən skan edin"</item>
     <item msgid="2092797862490235174">"Hazırdır"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"TV kanalları üçün skan"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV Kökləyici quraşdırması"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV Kökləyici quraşdırması"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV kökləyicisinin bağlantısı kəsildi."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TV kanalları üçün skan"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV Kökləyici quraşdırması"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV Kökləyici quraşdırması"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Şəbəkə TV Kökləyici quraşdırması"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV kökləyicisinin bağlantısı kəsildi."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Şəbəkə kökləyicisinin bağlantısı kəsildi."</string>
 </resources>
diff --git a/usbtuner-res/values-bg/strings.xml b/usbtuner-res/values-bg/strings.xml
index 0854c09..996023f 100644
--- a/usbtuner-res/values-bg/strings.xml
+++ b/usbtuner-res/values-bg/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Телевизионен тунер"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Телевизионен USB тунер"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Включване"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Изключване"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (БЕТА)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Моля, изчакайте обработването да завърши"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Изберете източник на канали"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Няма сигнал"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Превключването към „<xliff:g id="CHANNEL_NAME">%s</xliff:g>“ не бе успешно"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Превключването не бе успешно"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Софтуерът на тунера е актуализиран наскоро. Моля, сканирайте отново каналите."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Активирайте обемния звук от настройките за системния, за да включите аудиото"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Звукът не може да се възпроизведе. Моля, опитайте на друг телевизор"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Настройване на тунера за канали"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Настройване на телевизионния тунер"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Настройване на USB тунера за канали"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Настройване на мрежовия тунер"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Уверете се, че телевизорът ви е свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, може да се наложи да коригирате разположението или посоката й, за да получите оптимален брой канали. За най-добри резултати я поставете високо и близо до прозорец."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Уверете се, че USB тунерът е включен и свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, може да се наложи да коригирате разположението или посоката й, за да получите оптимален брой канали. За най-добри резултати я поставете високо и близо до прозорец."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Уверете се, че мрежовият тунер е включен и свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, може да се наложи да коригирате разположението или посоката й, за да уловите най-много канали. За най-добри резултати я поставете високо и близо до прозорец."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Напред"</item>
     <item msgid="727245208787621142">"Не сега"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Да се стартира ли отново настройването на каналите?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Така ще премахнете намерените от телевизионния тунер канали и ще сканирате за нови.\n\nУверете се, че телевизорът ви е свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, може да се наложи да коригирате разположението или посоката й, за да получите оптимален брой канали. За най-добри резултати я поставете високо и близо до прозорец."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Така ще премахнете намерените от USB тунера канали и ще сканирате за нови.\n\nУверете се, че USB тунерът е включен и свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, може да се наложи да коригирате разположението или посоката й, за да получите оптимален брой канали. За най-добри резултати я поставете високо и близо до прозорец."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Така ще премахнете намерените от мрежовия тунер канали и ще сканирате за нови.\n\nУверете се, че мрежовият тунер е включен и свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, може да се наложи да коригирате разположението или посоката й, за да уловите най-много канали. За най-добри резултати я поставете високо и близо до прозорец."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Напред"</item>
     <item msgid="235450158666155406">"Отказ"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Настройване на телевизионния тунер"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Настройване на USB тунера за канали"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Настройване на мрежовия тунер за канали"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Това може да отнеме няколко минути"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Временно няма достъп до тунера или той вече се използва за запис."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Няма намерени канали"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"При сканирането не бяха открити канали. Уверете се, че телевизорът ви е свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, коригирайте разположението или посоката й. За най-добри резултати я поставете високо и близо до прозорец и сканирайте отново."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"При сканирането не бяха открити канали. Уверете се, че USB тунерът е включен и свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, коригирайте разположението или посоката й. За най-добри резултати я поставете високо и близо до прозорец и сканирайте отново."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"При сканирането не бяха открити канали. Уверете се, че мрежовият тунер е включен и свързан с източник на телевизионен сигнал.\n\nАко използвате безжична антена, коригирайте разположението или посоката й. За най-добри резултати я поставете високо и близо до прозорец и сканирайте отново."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Повторно сканиране"</item>
     <item msgid="2092797862490235174">"Готово"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Сканиране за телевизионни канали"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Настройване на телевизионния тунер"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Настройване на телевизионния USB тунер"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Връзката с телевизионния USB тунер е прекратена."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Сканиране за телевизионни канали"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Настройване на телевизионния тунер"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Настройване на телевизионния USB тунер"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Настройване на Network TV Tuner"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Връзката с телевизионния USB тунер е прекратена."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Връзката с мрежовия тунер е прекратена."</string>
 </resources>
diff --git a/usbtuner-res/values-bn/strings.xml b/usbtuner-res/values-bn-rBD/strings.xml
similarity index 72%
rename from usbtuner-res/values-bn/strings.xml
rename to usbtuner-res/values-bn-rBD/strings.xml
index 236e2d9..8eb8a55 100644
--- a/usbtuner-res/values-bn/strings.xml
+++ b/usbtuner-res/values-bn-rBD/strings.xml
@@ -19,27 +19,26 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV টিউনার"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV টিউনার"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"চালু আছে"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"বন্ধ করুন"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"নেটওয়ার্ক TV টিউনার (বিটা)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"প্রক্রিয়াকরণ সম্পূর্ণ না হওয়া পর্যন্ত অনুগ্রহ করে অপেক্ষা করুন"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"আপনার চ্যানেলের উৎস নির্বাচন করুন"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"কোনো সংকেত নেই"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> এ টিউন করতে ব্যর্থ হয়েছে"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"টিউন করতে ব্যর্থ হয়েছে"</string>
-    <string name="ut_rescan_needed" msgid="2273655435759849436">"টিউনার সফ্টওয়্যার সম্প্রতি আপডেট করা হয়েছে৷ অনুগ্রহ করে চ্যানেলগুলি পুনরায় স্ক্যান করুন৷"</string>
+    <string name="ut_rescan_needed" msgid="2273655435759849436">"টিউনার সফ্টওয়্যার সম্প্রতি আপডেট করা হয়েছে৷ অনুগ্রহ করে চ্যানেলগুলি আবার স্ক্যান করুন৷"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"অডিও সক্ষম করতে সিস্টেম সাউন্ড সেটিংসে সারাউন্ড সাউন্ড সক্ষম করুন"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"অডিও প্লে করা যাবে না৷ অনুগ্রহ করে অন্য টিভি ব্যবহার করার চেষ্ট করুন"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"চ্যানেল টিউনার সেট আপ"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV টিউনার সেট আপ"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB চ্যানেল টিউনার সেটআপ"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"নেটওয়ার্ক টিউনার সেট আপ"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"আপনার TV একটি TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে কিনা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে অধিকাংশ চ্যানেল পাওয়ার জন্য আপনাকে সেটির অবস্থান এবং দিক ঠিক করতে হতে পারে৷ আরো ভাল ফলাফলের জন্য, এটিকে উচুঁতে কোনো জানলার সামনে রাখুন এবং আবার স্ক্যান করুন৷"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB টিউনার প্ল্যাগ ইন রয়েছে এবং একটি TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে তা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে অধিকাংশ চ্যানেল পাওয়ার জন্য আপনাকে সেটির অবস্থান এবং দিক ঠিক করতে হতে পারে৷ আরো ভাল ফলাফলের জন্য, এটিকে উচুঁতে কোনো জানলার সামনে রাখুন এবং আবার স্ক্যান করুন৷"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"নেটওয়ার্ক টিউনার চালু রয়েছে এবং কোনো TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে কিনা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে অধিকাংশ চ্যানেল পাওয়ার জন্য আপনাকে সেটির অবস্থান এবং দিক ঠিক করতে হতে পারে৷ আরো ভাল ফলাফলের জন্য, এটিকে উঁচুতে কোনো জানলার সামনে রেখে আবার স্ক্যান করুন৷"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"চালিয়ে যান"</item>
     <item msgid="727245208787621142">"এখনই নয়"</item>
   </string-array>
-    <string name="bt_setup_again_title" msgid="884713873101099572">"পুনরায় চ্যানেল সেট আপ করবেন?"</string>
+    <string name="bt_setup_again_title" msgid="884713873101099572">"আবার চ্যানেল সেট আপ করবেন?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"এটি TV টিউনার থেকে পাওয়া চ্যানেলগুলিকে মুছবে এবং নতুন চ্যানেলগুলির জন্য আবার স্ক্যান করবে৷\n\nআপনার TV একটি TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে কিনা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে অধিকাংশ চ্যানেল পাওয়ার জন্য আপনাকে সেটির অবস্থান এবং দিক ঠিক করতে হতে পারে৷ আরো ভাল ফলাফলের জন্য, এটিকে উচুঁতে কোনো জানলার সামনে রাখুন এবং আবার স্ক্যান করুন৷"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"এটি USB টিউনার থেকে পাওয়া চ্যানেলগুলিকে মুছবে এবং নতুন চ্যানেলগুলির জন্য আবার স্ক্যান করবে৷\n\nUSB টিউনার প্ল্যাগ ইন রয়েছে এবং একটি TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে তা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে অধিকাংশ চ্যানেল পাওয়ার জন্য আপনাকে সেটির অবস্থান এবং দিক ঠিক করতে হতে পারে৷ আরো ভাল ফলাফলের জন্য, এটিকে উচুঁতে কোনো জানলার সামনে রাখুন এবং আবার স্ক্যান করুন৷"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"এটি নেটওয়ার্ক টিউনার থেকে পাওয়া চ্যানেলগুলি মুছবে এবং নতুন চ্যানেলগুলিকে আবার স্ক্যান করবে৷\n\nনেটওয়ার্ক টিউনার চালু রয়েছে এবং কোনো TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে কিনা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে অধিকাংশ চ্যানেল পাওয়ার জন্য আপনাকে সেটির অবস্থান এবং দিক ঠিক করতে হতে পারে৷ আরো ভাল ফলাফলের জন্য, এটিকে উঁচুতে কোনো জানলার সামনে রেখে আবার স্ক্যান করুন৷"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"চালিয়ে যান"</item>
     <item msgid="235450158666155406">"বাতিল করুন"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV টিউনার সেট আপ"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB চ্যানেল টিউনার সেটআপ"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"নেটওয়ার্ক চ্যানেল টিউনার সেটআপ"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"এটি কয়েক মিনিট সময় নিতে পারে"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"টিউনার অস্থায়ীভাবে অনুপলব্ধ বা রেকডিংয়ে ইতিমধ্যেই ব্যবহৃত হয়েছে৷"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"কোনো চ্যানেল খুঁজে পাওয়া যায়নি"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"স্ক্যান করে কোনো চ্যানেল খুঁজে পাওয়া যায়নি৷ আপনার TV একটি TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে কিনা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে সেটির অবস্থান এবং দিক ঠিক করুন৷ আরো ভাল ফলাফলের জন্য, এটিকে উচুঁতে কোনো জানলার সামনে রাখুন এবং আবার স্ক্যান করুন৷"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"স্ক্যান করে কোনো চ্যানেল খুঁজে পাওয়া যায়নি৷ USB টিউনার প্ল্যাগ ইন রয়েছে এবং একটি TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে তা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে সেটির অবস্থান এবং দিক ঠিক করুন৷ আরো ভাল ফলাফলের জন্য, এটিকে উচুঁতে কোনো জানলার সামনে রাখুন এবং আবার স্ক্যান করুন৷"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"স্ক্যান করে কোনো চ্যানেল খুঁজে পাওয়া যায়নি৷ নেটওয়ার্ক টিউনার চালু এবং কোনো TV সিগন্যাল উৎসের সাথে সংযুক্ত রয়েছে কিনা যাচাই করুন৷\n\nযদি কোনো ওভার-দ্য-এয়ার অ্যান্টেনা ব্যবহার করা হয় তাহলে সেটির অবস্থান এবং দিক ঠিক করুন৷ আরো ভাল ফলাফলের জন্য, এটিকে উঁচুতে কোনো জানলার সামনে রেখে আবার স্ক্যান করুন৷"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"আবার স্ক্যান করুন"</item>
     <item msgid="2092797862490235174">"সম্পন্ন"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"টিভি চ্যানেলগুলি স্ক্যান করুন"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV টিউনার সেট আপ"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB টিভি টিউনার সেট আপ"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB টিভি টিউনারের সংযোগ বিচ্ছিন্ন হয়েছে।"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"টিভি চ্যানেলগুলি স্ক্যান করুন"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV টিউনার সেট আপ"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB টিভি টিউনার সেট আপ"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"নেটওয়ার্ক TV টিউনার সেট আপ"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB টিভি টিউনারের সংযোগ বিচ্ছিন্ন হয়েছে।"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"নেটওয়ার্ক টিউনারের সংযোগ বিচ্ছিন্ন হয়েছে।"</string>
 </resources>
diff --git a/usbtuner-res/values-ca/strings.xml b/usbtuner-res/values-ca/strings.xml
index af90c3d..d005204 100644
--- a/usbtuner-res/values-ca/strings.xml
+++ b/usbtuner-res/values-ca/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sintonitzador de televisió"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Sintonitzador de televisió USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Activa"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Desactiva"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Sintonitzador de televisió en xarxa (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Espera per finalitzar el processament"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Selecciona la font del canal"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Sense senyal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"No s\'ha pogut sintonitzar <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"No s\'ha pogut sintonitzar"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"El programari del sintonitzador s\'ha actualitzat fa poc. Torna a cercar els canals."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Activa el so envoltant a la configuració de so del sistema per activar l\'àudio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"No es pot reproduir l\'àudio. Prova-ho amb un altre televisor."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuració del sintonitzador de canals"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configuració del sintonitzador de televisió"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configuració del sintonitzador de canals USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configuració del sintonitzador en xarxa"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Verifica que el teu televisor estigui connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, pot ser que calgui ajustar-ne la ubicació o la direcció per rebre el màxim de canals. Per obtenir els millors resultats, col·loca-la en un lloc elevat i a prop d\'una finestra."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Verifica que el sintonitzador USB estigui endollat i connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, pot ser que calgui ajustar-ne la ubicació o la direcció per rebre el màxim de canals. Per obtenir els millors resultats, col·loca-la en un lloc elevat i a prop d\'una finestra."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Comprova que el sintonitzador en xarxa estigui engegat i connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, pot ser que calgui ajustar-ne la ubicació o la direcció per rebre el màxim de canals. Per obtenir uns resultats millors, col·loca-la en un lloc elevat i a prop d\'una finestra."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continua"</item>
     <item msgid="727245208787621142">"Ara no"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Vols tornar a executar la configuració de canals?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Això farà que se suprimeixin del sintonitzador de televisió els canals que s\'han trobat i que es tornin a cercar canals nous.\n\nVerifica que el teu televisor estigui connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, pot ser que calgui ajustar-ne la ubicació o la direcció per rebre el màxim de canals. Per obtenir els millors resultats, col·loca-la en un lloc elevat i a prop d\'una finestra."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Això farà que se suprimeixin del sintonitzador USB els canals que s\'han trobat i que es tornin a cercar canals nous.\n\nVerifica que el sintonitzador USB estigui endollat i connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, pot ser que calgui ajustar-ne la ubicació o la direcció per rebre el màxim de canals. Per obtenir els millors resultats, col·loca-la en un lloc elevat i a prop d\'una finestra."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Això farà que se suprimeixin del sintonitzador en xarxa els canals trobats i que se\'n tornin a cercar de nous.\n\nComprova que el sintonitzador en xarxa estigui engegat i connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, pot ser que calgui ajustar-ne la ubicació o la direcció per rebre el màxim de canals. Per obtenir uns resultats millors, col·loca-la en un lloc elevat i a prop d\'una finestra."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continua"</item>
     <item msgid="235450158666155406">"Cancel·la"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configuració del sintonitzador de televisió"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configuració del sintonitzador de canals USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configuració del sintonitzador de canals en xarxa"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Aquesta acció pot tardar uns quants minuts"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"El sintonitzador no està disponible en aquest moment o bé ja s\'està utilitzant en un enregistrament."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"No s\'ha trobat cap canal"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"No s\'ha trobat cap canal. Verifica que el teu televisor estigui connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, ajusta\'n la ubicació o la direcció. Per obtenir els millors resultats, col·loca-la en un lloc elevat i a prop d\'una finestra i torna a cercar canals."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"La cerca no ha trobat cap canal. Verifica que el sintonitzador USB estigui endollat i connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, ajusta\'n la ubicació o la direcció. Per obtenir els millors resultats, col·loca-la en un lloc elevat i a prop d\'una finestra i torna a cercar."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"No s\'ha trobat cap canal. Comprova que el sintonitzador en xarxa estigui engegat i connectat a una font de senyal de televisió.\n\nSi fas servir una antena aèria, ajusta\'n la ubicació o la direcció. Per obtenir uns resultats millors, col·loca-la en un lloc elevat i a prop d\'una finestra i torna a cercar."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Torna a cercar"</item>
     <item msgid="2092797862490235174">"Fet"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Cerca canals de televisió"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configuració del sintonitzador de televisió"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configuració del sintonitzador de televisió USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"El sintonitzador de televisió USB no està connectat."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Cerca canals de televisió"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configuració del sintonitzador de televisió"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configuració del sintonitzador de televisió USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configuració del sintonitzador de televisió en xarxa"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"El sintonitzador de televisió USB no està connectat."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"El sintonitzador de la xarxa no està connectat."</string>
 </resources>
diff --git a/usbtuner-res/values-cs/strings.xml b/usbtuner-res/values-cs/strings.xml
index 151083c..6943604 100644
--- a/usbtuner-res/values-cs/strings.xml
+++ b/usbtuner-res/values-cs/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Televizní tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Televizní tuner USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Zapnout"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Vypnout"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Síťový televizní tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Vyčkejte prosím, než bude zpracování dokončeno"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Vyberte zdroj kanálu"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Žádný signál"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Kanál <xliff:g id="CHANNEL_NAME">%s</xliff:g> se nepodařilo naladit"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Nelze naladit"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Software tuneru byl nedávno aktualizován. Vyhledejte prosím kanály znovu."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Chcete-li zapnout zvuk, v nastavení systémového zvuku povolte prostorový zvuk"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Zvuk nelze přehrát. Zkuste použít jinou televizi."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Nastavení tuneru kanálů"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Nastavení televizního tuneru"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Nastavení tuneru kanálů USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Nastavení síťového tuneru"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Zkontrolujte, zda je televize připojena ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, možná budete muset za účelem příjmu co největšího počtu kanálů upravit její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Zkontrolujte, zda je tuner USB připojen k zařízení a ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, možná budete muset za účelem příjmu co největšího počtu kanálů upravit její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Zkontrolujte, zda je síťový tuner zapnut a připojen ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, možná budete muset za účelem příjmu co největšího počtu kanálů upravit její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Pokračovat"</item>
     <item msgid="727245208787621142">"Teď ne"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Znovu spustit nastavení kanálů?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Tímto odstraníte kanály nalezené pomocí televizního tuneru a znovu vyhledáte nové kanály.\n\nZkontrolujte, zda je televize připojena ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, možná budete muset za účelem příjmu co největšího počtu kanálů upravit její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Tímto odstraníte kanály nalezené pomocí tuneru USB a znovu vyhledáte nové kanály.\n\nZkontrolujte, zda je tuner USB připojen k zařízení a ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, možná budete muset za účelem příjmu co největšího počtu kanálů upravit její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Tímto odstraníte kanály nalezené pomocí síťového tuneru a znovu vyhledáte nové kanály.\n\nZkontrolujte, zda je síťový tuner zapnut a připojen ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, možná budete muset za účelem příjmu co největšího počtu kanálů upravit její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Pokračovat"</item>
     <item msgid="235450158666155406">"Zrušit"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Nastavení televizního tuneru"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Nastavení tuneru kanálů USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Nastavení kanálů síťového tuneru"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Tato akce může trvat několik minut."</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuner dočasně není k dispozici, případně je právě používán k nahrávání."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -82,12 +82,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nebyly nalezeny žádné kanály"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Při vyhledávání nebyly nalezeny žádné kanály. Zkontrolujte, zda je televize připojena ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, upravte její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna. Poté spusťte vyhledávání znovu."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Při vyhledávání nebyly nalezeny žádné kanály. Zkontrolujte, zda je tuner USB připojen k zařízení a ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, upravte její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna. Poté spusťte vyhledávání znovu."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Při vyhledávání nebyly nalezeny žádné kanály. Zkontrolujte, zda je síťový tuner zapnut a připojen ke zdroji televizního signálu.\n\nPokud používáte bezdrátovou anténu, upravte její umístění nebo nasměrování. Nejlepších výsledků dosáhnete, pokud ji umístíte vysoko a blízko okna. Poté spusťte vyhledávání znovu."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Znovu vyhledat"</item>
     <item msgid="2092797862490235174">"Hotovo"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Vyhledejte televizní kanály"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Nastavení televizního tuneru"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Nastavení televizního tuneru USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Televizní tuner USB byl odpojen."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Vyhledejte televizní kanály"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Nastavení televizního tuneru"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Nastavení televizního tuneru USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Nastavení síťového televizního tuneru"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Televizní tuner USB byl odpojen."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Síťový tuner byl odpojen."</string>
 </resources>
diff --git a/usbtuner-res/values-da/strings.xml b/usbtuner-res/values-da/strings.xml
index cea5d3c..96a902b 100644
--- a/usbtuner-res/values-da/strings.xml
+++ b/usbtuner-res/values-da/strings.xml
@@ -19,27 +19,26 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV Tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-tuner til fjernsynet"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Til"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Fra"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Netværkstuner til tv (beta)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Vent, mens behandlingen afsluttes"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Vælg din kanalkilde"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Intet signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> kunne ikke indlæses"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Indlæsningen lykkedes ikke"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Tunerens software er blevet opdateret for nylig. Scan efter kanalerne igen."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Aktivér surroundsound i systemets lydindstillinger for at aktivere lyd"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Der kan ikke afspilles lyd. Prøv på et andet fjernsyn"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Konfiguration af kanaltuneren"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Konfiguration med TV Tuner"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Konfiguration af USB-kanaltuneren"</string>
-    <string name="bt_setup_new_description" msgid="256690722062003128">"Kontrollér, at dit fjernsyn er forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
-    <string name="ut_setup_new_description" msgid="2610122936163002137">"Kontrollér, at USB-tuneren er tilsluttet og forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Konfiguration af netværkstuner"</string>
+    <string name="bt_setup_new_description" msgid="256690722062003128">"Tjek, at dit fjernsyn er forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
+    <string name="ut_setup_new_description" msgid="2610122936163002137">"Tjek, at USB-tuneren er tilsluttet og forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Tjek, at netværkstuneren er tændt og sluttet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Fortsæt"</item>
     <item msgid="727245208787621142">"Ikke nu"</item>
   </string-array>
     <string name="bt_setup_again_title" msgid="884713873101099572">"Vil du gentage kanalkonfigurationen?"</string>
-    <string name="bt_setup_again_description" msgid="1247792492948741337">"Dette fjerner de kanaler, som blev fundet, fra fjernsynets tuner og scanner efter nye kanaler igen.\n\nKontrollér, at dit fjernsyn er forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
-    <string name="ut_setup_again_description" msgid="7837706010887799255">"Denne handling fjerner de kanaler, der blev fundet af USB-tuneren, og starter en ny scanning efter kanaler.\n\nKontrollér, at USB-tuneren er tilsluttet og forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
+    <string name="bt_setup_again_description" msgid="1247792492948741337">"Dette fjerner de kanaler, som blev fundet, fra fjernsynets tuner og scanner efter nye kanaler igen.\n\nTjek, at dit fjernsyn er forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
+    <string name="ut_setup_again_description" msgid="7837706010887799255">"Denne handling fjerner de kanaler, der blev fundet af USB-tuneren, og starter en ny scanning efter kanaler.\n\nTjek, at USB-tuneren er tilsluttet og forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Denne handling fjerner de kanaler, der blev fundet af netværkstuneren, og starter en ny kanalsøgning.\n\nTjek, at netværkstuneren er tændt og sluttet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, kan det være nødvendigt at justere dens position eller retning for at modtage flest muligt kanaler. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Fortsæt"</item>
     <item msgid="235450158666155406">"Annuller"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Konfiguration med fjernsynets tuner"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Konfiguration af USB-kanaltuneren"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Konfiguration af netværkstuner til kanalsøgning"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Dette kan tage flere minutter"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuneren er midlertidigt utilgængelig eller benyttes allerede til en optagelse."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -74,14 +74,17 @@
     <item msgid="2480490326672924828">"Scan igen"</item>
   </string-array>
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Der blev ikke fundet nogen kanaler"</string>
-    <string name="bt_result_not_found_description" msgid="7378208337325024042">"Der blev ikke fundet nogen kanaler under scanningen. Kontrollér, at dit fjernsyn er forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, skal du justere dens position eller retning. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue. Scan igen."</string>
-    <string name="ut_result_not_found_description" msgid="1080746285957681414">"Der blev ikke fundet nogen kanaler under scanningen. Kontrollér, at USB-tuneren er tilsluttet og forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, skal du justere dens position eller retning. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue. Scan igen."</string>
+    <string name="bt_result_not_found_description" msgid="7378208337325024042">"Der blev ikke fundet nogen kanaler under scanningen. Tjek, at dit fjernsyn er forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, skal du justere dens position eller retning. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue. Scan igen."</string>
+    <string name="ut_result_not_found_description" msgid="1080746285957681414">"Der blev ikke fundet nogen kanaler under scanningen. Tjek, at USB-tuneren er tilsluttet og forbundet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, skal du justere dens position eller retning. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue. Scan igen."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Der blev ikke fundet nogen kanaler under søgningen. Tjek, at netværkstuneren er tændt og sluttet til en tv-signalkilde.\n\nHvis du bruger en luftantenne, skal du justere dens position eller retning. Du opnår det bedste resultat ved at placere den højt oppe og i nærheden af et vindue. Søg igen."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Scan igen"</item>
     <item msgid="2092797862490235174">"Udført"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Scan efter tv-kanaler"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Konfiguration med TV Tuner"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Konfiguration af USB-TV Tuner"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-tuneren til fjernsynet af frakoblet."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Søg efter tv-kanaler"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Konfiguration af tuner til fjernsynet"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Konfiguration af USB-tuner til fjernsynet"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Konfiguration af netværkstuner til fjernsynet"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-tuneren til fjernsynet er ikke tilsluttet."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Netværkstuneren er ikke tilsluttet."</string>
 </resources>
diff --git a/usbtuner-res/values-de/strings.xml b/usbtuner-res/values-de/strings.xml
index eab5fb1..b0f17df 100644
--- a/usbtuner-res/values-de/strings.xml
+++ b/usbtuner-res/values-de/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV-Tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-TV-Tuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"An"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Aus"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Netzwerk-TV-Tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Bitte warten Sie, bis die Verarbeitung abgeschlossen ist"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Kanalquelle auswählen"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Kein Signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"\"<xliff:g id="CHANNEL_NAME">%s</xliff:g>\" konnte nicht eingestellt werden"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Fehler beim Einstellen"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Die Tunersoftware wurde kürzlich aktualisiert. Bitte führen Sie die Kanalsuche noch einmal durch."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Aktivieren Sie in den Systemeinstellungen Surround-Sound, um Audio einschalten zu können"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Audio kann nicht wiedergegeben werden. Bitte versuch es mit einem anderen Fernseher."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kanaleinrichtung über den Tuner"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV-Tuner einrichten"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Kanaleinrichtung über den USB-Tuner"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Einrichtung des Netzwerk-Tuners"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Vergewissern Sie sich, dass Ihr Fernseher mit einer TV-Signalquelle verbunden ist.\n\nWenn Sie eine terrestrische Antenne verwenden, ändern Sie die Position oder Ausrichtung, um mehr Kanäle zu finden. Die besten Ergebnisse erhalten Sie, wenn Sie sie an eine erhöhte Position in Fensternähe stellen."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Vergewissern Sie sich, dass der USB-Tuner angeschlossen und mit einer TV-Signalquelle verbunden ist.\n\nWenn Sie eine terrestrische Antenne verwenden, ändern Sie die Position oder Ausrichtung, um mehr Kanäle zu finden. Die besten Ergebnisse erhalten Sie, wenn Sie sie an einer erhöhten Position in Fensternähe stellen."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Vergewissere dich, dass der Netzwerk-Tuner eingeschaltet und mit einer TV-Signalquelle verbunden ist.\n\nWenn du eine terrestrische Antenne verwendest, ändere die Position oder Ausrichtung, um mehr Kanäle zu empfangen. Die besten Ergebnisse erhältst du, wenn du die Antenne an eine erhöhte Position in Fensternähe stellst."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Weiter"</item>
     <item msgid="727245208787621142">"Jetzt nicht"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Kanaleinrichtung erneut durchführen?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Dies entfernt die vom TV-Tuner gefundenen Kanäle und sucht noch einmal nach neuen Kanälen.\n\nVergewissern Sie sich, dass Ihr Fernseher mit einer TV-Signalquelle verbunden ist.\n\nWenn Sie eine terrestrische Antenne verwenden, ändern Sie die Position oder Ausrichtung, um mehr Kanäle zu finden. Die besten Ergebnisse erhalten Sie, wenn Sie sie an eine erhöhte Position in Fensternähe stellen."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Durch diese Aktion werden die gefundenen Kanäle vom USB-Tuner entfernt und die Kanalsuche wird erneut gestartet.\n\nVergewissern Sie sich, dass der USB-Tuner angeschlossen und mit einer TV-Signalquelle verbunden ist.\n\nWenn Sie eine terrestrische Antenne verwenden, ändern Sie die Position oder Ausrichtung, um mehr Kanäle zu finden. Die besten Ergebnisse erhalten Sie, wenn Sie sie an einer erhöhten Position in Fensternähe stellen."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Durch diese Aktion werden die vom Netzwerk-Tuner gefundenen Kanäle entfernt und die Kanalsuche wird neu gestartet.\n\nVergewissere dich, dass der Netzwerk-Tuner eingeschaltet und mit einer TV-Signalquelle verbunden ist.\n\nWenn du eine terrestrische Antenne verwendest, ändere die Position oder Ausrichtung, um mehr Kanäle zu empfangen. Die besten Ergebnisse erhältst du, wenn du die Antenne an eine erhöhte Position in Fensternähe stellst."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Weiter"</item>
     <item msgid="235450158666155406">"Abbrechen"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV-Tuner einrichten"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Kanaleinrichtung über den USB-Tuner"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Kanaleinrichtung über den Netzwerk-Tuner"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Dies kann einige Minuten dauern"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Der Tuner ist vorübergehend nicht verfügbar oder wird schon für eine Aufnahme verwendet."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Keine Kanäle gefunden"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Bei der Suche wurden keine Kanäle gefunden. Vergewissern Sie sich, dass Ihr Fernseher mit einer TV-Signalquelle verbunden ist.\n\nWenn Sie eine terrestrische Antenne verwenden, ändern Sie die Position oder Ausrichtung. Um die besten Ergebnisse zu erhalten, stellen Sie sie an eine erhöhte Position in Fensternähe und führen Sie die Suche noch einmal durch."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Bei der Suche wurden keine Kanäle gefunden. Vergewissern Sie sich, dass der USB-Tuner angeschlossen und mit einer TV-Signalquelle verbunden ist.\n\nWenn Sie eine terrestrische Antenne verwenden, ändern Sie die Position oder Ausrichtung. Die besten Ergebnisse erhalten Sie, wenn Sie sie an einer erhöhten Position in Fensternähe stellen. Führen Sie dann die Suche erneut durch."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Bei der Suche wurden keine Kanäle gefunden. Vergewissere dich, dass der Netzwerk-Tuner eingeschaltet und mit einer TV-Signalquelle verbunden ist.\n\nWenn du eine terrestrische Antenne verwendest, ändere die Position oder Ausrichtung. Die besten Ergebnisse erhältst du, wenn du sie an eine erhöhte Position in Fensternähe stellst und die Suche noch einmal durchführst."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Noch einmal suchen"</item>
     <item msgid="2092797862490235174">"Fertig"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Nach TV-Kanälen suchen"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV-Tuner einrichten"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB-TV-Tuner einrichten"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Verbindung zum USB-TV-Empfänger wurde aufgehoben."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Nach TV-Kanälen suchen"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Einrichtung des TV-Tuners"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Einrichtung des USB-TV-Tuners"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Einrichtung des Netzwerk-TV-Tuners"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Verbindung zum USB-TV-Tuner wurde aufgehoben."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Verbindung zum Netzwerk-Tuner wurde aufgehoben."</string>
 </resources>
diff --git a/usbtuner-res/values-el/strings.xml b/usbtuner-res/values-el/strings.xml
index 6a033e3..1ea637d 100644
--- a/usbtuner-res/values-el/strings.xml
+++ b/usbtuner-res/values-el/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Δέκτης τηλεόρασης"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Δέκτης τηλεόρασης USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Ενεργό"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Ανενεργό"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Δέκτης τηλεόρασης δικτύου (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Περιμένετε να ολοκληρωθεί η επεξεργασία"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Επιλέξτε την πηγή του καναλιού σας"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Χωρίς σήμα"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Αποτυχία συντονισμού <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Αποτυχία συντονισμού"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Το λογισμικό δέκτη ενημερώθηκε πρόσφατα. Επαναλάβετε τη σάρωση των καναλιών."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Ενεργοποιήστε τον περιφερειακό ήχο στις ρυθμίσεις ήχου συστήματος για να ενεργοποιήσετε τον ήχο"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Δεν είναι δυνατή η αναπαραγωγή ήχου. Δοκιμάστε μια άλλη τηλεόραση."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Ρύθμιση δέκτη καναλιών"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Ρύθμιση δέκτη τηλεόρασης"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Ρύθμιση δέκτη καναλιών USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Ρύθμιση δέκτη δικτύου"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Βεβαιωθείτε ότι η τηλεόρασή σας είναι συνδεδεμένη σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, ίσως χρειαστεί να προσαρμόσετε την τοποθέτηση ή την κατεύθυνσή της για να λάβετε περισσότερα κανάλια. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε ένα παράθυρο."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Βεβαιωθείτε ότι ο δέκτης USB είναι συνδεδεμένος στην πρίζα και σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, ίσως χρειαστεί να προσαρμόσετε την τοποθέτηση ή την κατεύθυνσή της για να λάβετε περισσότερα κανάλια. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε ένα παράθυρο."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Βεβαιωθείτε ότι ο δέκτης του δικτύου είναι ενεργοποιημένος και συνδεδεμένος σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, ίσως χρειαστεί να προσαρμόσετε την τοποθέτηση ή την κατεύθυνσή της για να λάβετε περισσότερα κανάλια. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε ένα παράθυρο."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Συνέχεια"</item>
     <item msgid="727245208787621142">"Όχι τώρα"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Επανάληψη ρύθμισης καναλιών;"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Με αυτόν τον τρόπο θα καταργηθούν τα κανάλια που βρέθηκαν από τον δέκτη τηλεόρασης και θα γίνει ξανά σάρωση για νέα κανάλια.\n\nΒεβαιωθείτε ότι η τηλεόρασή σας είναι συνδεδεμένη σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, ίσως χρειαστεί να προσαρμόσετε την τοποθέτηση ή την κατεύθυνσή της για να λάβετε περισσότερα κανάλια. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε ένα παράθυρο."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Με αυτόν τον τρόπο θα καταργηθούν τα κανάλια που βρέθηκαν από τον δέκτη USB και θα γίνει ξανά σάρωση για νέα κανάλια.\n\nΒεβαιωθείτε ότι ο δέκτης USB είναι συνδεδεμένος στην πρίζα και σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, ίσως χρειαστεί να προσαρμόσετε την τοποθέτηση ή την κατεύθυνσή της για να λάβετε περισσότερα κανάλια. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε ένα παράθυρο."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Με αυτόν τον τρόπο, τα κανάλια που βρέθηκαν από τον δέκτη του δικτύου θα καταργηθούν και θα γίνει ξανά σάρωση για νέα κανάλια.\n\nΒεβαιωθείτε ότι ο δέκτης του δικτύου είναι ενεργοποιημένος και συνδεδεμένος σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, ίσως χρειαστεί να προσαρμόσετε την τοποθέτηση ή την κατεύθυνσή της για να λάβετε περισσότερα κανάλια. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε ένα παράθυρο."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Συνέχεια"</item>
     <item msgid="235450158666155406">"Ακύρωση"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Ρύθμιση δέκτη τηλεόρασης"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Ρύθμιση δέκτη καναλιών USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Ρύθμιση δέκτη καναλιών δικτύου"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Αυτό μπορεί να διαρκέσει αρκετά λεπτά"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Ο δέκτης δεν είναι διαθέσιμος προσωρινά ή χρησιμοποιείται ήδη από την εγγραφή."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Δεν βρέθηκαν κανάλια"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Δεν βρέθηκαν κανάλια κατά τη σάρωση. Βεβαιωθείτε ότι η τηλεόρασή σας είναι συνδεδεμένη σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, προσαρμόστε την τοποθέτηση ή την κατεύθυνσή της. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε ένα παράθυρο και επαναλάβετε τη σάρωση."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Δεν βρέθηκαν κανάλια κατά τη σάρωση. Βεβαιωθείτε ότι ο δέκτης USB είναι συνδεδεμένος στην πρίζα και σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, προσαρμόστε την τοποθέτηση ή την κατεύθυνσή της. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε ένα παράθυρο και επαναλάβετε τη σάρωση."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Δεν εντοπίστηκε κανένα κανάλι κατά τη σάρωση. Βεβαιωθείτε ότι ο δέκτης του δικτύου είναι ενεργοποιημένος και συνδεδεμένος σε μια πηγή τηλεοπτικού σήματος.\n\nΕάν χρησιμοποιείτε ασύρματη κεραία, προσαρμόστε την τοποθέτηση ή την κατεύθυνσή της. Για καλύτερα αποτελέσματα, τοποθετήστε την ψηλά και κοντά σε κάποιο παράθυρο και επαναλάβετε τη σάρωση."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Εκ νέου σάρωση"</item>
     <item msgid="2092797862490235174">"Ολοκληρώθηκε"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Σάρωση για τηλεοπτικά κανάλια"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Ρύθμιση δέκτη τηλεόρασης"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Ρύθμιση δέκτη τηλεόρασης USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Ο δέκτης τηλεόρασης USB έχει αποσυνδεθεί."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Σάρωση για τηλεοπτικά κανάλια"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Ρύθμιση δέκτη τηλεόρασης"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Ρύθμιση δέκτη τηλεόρασης USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Ρύθμιση δέκτη τηλεόρασης δικτύου"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Ο δέκτης τηλεόρασης USB έχει αποσυνδεθεί."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Ο δέκτης δικτύου έχει αποσυνδεθεί."</string>
 </resources>
diff --git a/usbtuner-res/values-en-rAU/strings.xml b/usbtuner-res/values-en-rAU/strings.xml
index 11e639f..dccba99 100644
--- a/usbtuner-res/values-en-rAU/strings.xml
+++ b/usbtuner-res/values-en-rAU/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV Tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV Tuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"On"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Off"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Please wait to finish processing"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Select your channel source"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"No Signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Failed to tune to <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Failed to tune"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Tuner software has been recently updated. Please re-scan the channels."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"To enable audio, enable surround sound in system sound settings"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Cannot play audio. Please try another TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Channel tuner setup"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV Tuner setup"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB channel tuner setup"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Network Tuner Setup"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Check that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Check that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Verify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continue"</item>
     <item msgid="727245208787621142">"Not now"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Re-run channel setup?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"This will remove the channels found from the TV tuner and scan for new channels again.\n\nCheck that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"This will remove the channels found from the USB tuner and scan for new channels again.\n\nCheck that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"This will remove the channels found from the network tuner and scan for new channels again.\n\nVerify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continue"</item>
     <item msgid="235450158666155406">"Cancel"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV tuner setup"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB channel tuner setup"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Network channel tuner setup"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"This may take several minutes"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuner is temporarily unavailable or already used by recording."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"No channels found"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"The scan did not find any channels. Check that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"The scan did not find any channels. Check that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air aerial, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"The scan did not find any channels. Verify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Scan again"</item>
     <item msgid="2092797862490235174">"Finished"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Scan for TV channels"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV Tuner setup"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV Tuner setup"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV tuner disconnected."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Scan for TV channels"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV Tuner setup"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV Tuner setup"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Network TV Tuner setup"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV tuner disconnected."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Network tuner disconnected."</string>
 </resources>
diff --git a/usbtuner-res/values-en-rGB/strings.xml b/usbtuner-res/values-en-rGB/strings.xml
index 11e639f..dccba99 100644
--- a/usbtuner-res/values-en-rGB/strings.xml
+++ b/usbtuner-res/values-en-rGB/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV Tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV Tuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"On"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Off"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Please wait to finish processing"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Select your channel source"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"No Signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Failed to tune to <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Failed to tune"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Tuner software has been recently updated. Please re-scan the channels."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"To enable audio, enable surround sound in system sound settings"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Cannot play audio. Please try another TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Channel tuner setup"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV Tuner setup"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB channel tuner setup"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Network Tuner Setup"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Check that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Check that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Verify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continue"</item>
     <item msgid="727245208787621142">"Not now"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Re-run channel setup?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"This will remove the channels found from the TV tuner and scan for new channels again.\n\nCheck that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"This will remove the channels found from the USB tuner and scan for new channels again.\n\nCheck that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"This will remove the channels found from the network tuner and scan for new channels again.\n\nVerify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continue"</item>
     <item msgid="235450158666155406">"Cancel"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV tuner setup"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB channel tuner setup"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Network channel tuner setup"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"This may take several minutes"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuner is temporarily unavailable or already used by recording."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"No channels found"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"The scan did not find any channels. Check that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"The scan did not find any channels. Check that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air aerial, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"The scan did not find any channels. Verify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Scan again"</item>
     <item msgid="2092797862490235174">"Finished"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Scan for TV channels"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV Tuner setup"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV Tuner setup"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV tuner disconnected."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Scan for TV channels"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV Tuner setup"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV Tuner setup"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Network TV Tuner setup"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV tuner disconnected."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Network tuner disconnected."</string>
 </resources>
diff --git a/usbtuner-res/values-en-rIN/strings.xml b/usbtuner-res/values-en-rIN/strings.xml
index 11e639f..dccba99 100644
--- a/usbtuner-res/values-en-rIN/strings.xml
+++ b/usbtuner-res/values-en-rIN/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV Tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV Tuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"On"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Off"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Please wait to finish processing"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Select your channel source"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"No Signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Failed to tune to <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Failed to tune"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Tuner software has been recently updated. Please re-scan the channels."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"To enable audio, enable surround sound in system sound settings"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Cannot play audio. Please try another TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Channel tuner setup"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV Tuner setup"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB channel tuner setup"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Network Tuner Setup"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Check that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Check that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Verify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continue"</item>
     <item msgid="727245208787621142">"Not now"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Re-run channel setup?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"This will remove the channels found from the TV tuner and scan for new channels again.\n\nCheck that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"This will remove the channels found from the USB tuner and scan for new channels again.\n\nCheck that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"This will remove the channels found from the network tuner and scan for new channels again.\n\nVerify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or direction to receive the most channels. For best results, place it high and near a window."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continue"</item>
     <item msgid="235450158666155406">"Cancel"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV tuner setup"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB channel tuner setup"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Network channel tuner setup"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"This may take several minutes"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuner is temporarily unavailable or already used by recording."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"No channels found"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"The scan did not find any channels. Check that your TV is connected to a TV signal source.\n\nIf using an over-the-air aerial, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"The scan did not find any channels. Check that the USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air aerial, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"The scan did not find any channels. Verify the network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air antenna, adjust its placement or direction. For best results, place it high and near a window and scan again."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Scan again"</item>
     <item msgid="2092797862490235174">"Finished"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Scan for TV channels"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV Tuner setup"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV Tuner setup"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV tuner disconnected."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Scan for TV channels"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV Tuner setup"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV Tuner setup"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Network TV Tuner setup"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV tuner disconnected."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Network tuner disconnected."</string>
 </resources>
diff --git a/usbtuner-res/values-es-rUS/strings.xml b/usbtuner-res/values-es-rUS/strings.xml
index da7ec69..cca69f4 100644
--- a/usbtuner-res/values-es-rUS/strings.xml
+++ b/usbtuner-res/values-es-rUS/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sintonizador de TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Sintonizador de TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Activar"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Desactivar"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Sintonizador de TV de red (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Espera a que finalice el procesamiento"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Seleccionar la fuente del canal"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Sin señal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"No se pudo sintonizar el canal <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"No se pudo sintonizar el canal"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"El software del sintonizador se actualizó recientemente. Vuelve a buscar los canales."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Para habilitar el audio, deberás activar el sonido envolvente en la configuración del sistema de sonido"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"No se puede reproducir el audio. Intenta usar otra TV."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuración del sintonizador de canales"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configuración del sintonizador de TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configuración del sintonizador de canales USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configuración del sintonizador de red"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Verifica que tu TV esté conectada a una fuente de señal de TV.\n\nSi usas una antena inalámbrica, es posible que tengas que ajustar su posición o dirección para recibir la mayor cantidad de canales posible. Para obtener mejores resultados, ubica la antena en un lugar alto y cerca de una ventana."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Verifica que el sintonizador USB esté enchufado y conectado a una fuente de señal de TV.\n\nSi usas una antena inalámbrica, es posible que necesites ajustar su ubicación y dirección para recibir la mayor cantidad de canales. Para obtener mejores resultados, ubica la antena en un lugar alto y cerca de una ventana."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Comprueba que el sintonizador de red esté encendido y conectado a una fuente de señal de TV.\n\nSi estás usando una antena inalámbrica, es posible que debas ajustar su ubicación o dirección para recibir la mayoría de los canales. Si deseas obtener mejores resultados, colócala en un lugar alto y cerca de una ventana."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continuar"</item>
     <item msgid="727245208787621142">"Ahora no"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"¿Quieres volver a configurar los canales?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Esta acción quitará los canales encontrados desde el sintonizador de TV y se volverán a buscar canales nuevos.\n\nVerifica que tu TV esté conectada a una fuente de señal de TV.\n\nSi usas una antena inalámbrica, es posible que tengas que ajustar su posición o dirección para recibir la mayor cantidad de canales posible. Para obtener mejores resultados, ubica la antena en un lugar alto y cerca de una ventana."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Esta acción quitará los canales encontrados desde el sintonizador de TV y se volverán a buscar canales nuevos.\n\nVerifica que el sintonizador USB esté enchufado y conectado a una fuente de señal de TV.\n\nSi usas una antena inalámbrica, es posible que necesites ajustar su ubicación y dirección para recibir la mayor cantidad de canales. Para obtener mejores resultados, ubica la antena en un lugar alto y cerca de una ventana."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"De esta manera, se quitarán los canales encontrados desde el sintonizador de red y se buscarán canales nuevos.\n\nComprueba que el sintonizador de red esté encendido y conectado a una fuente de señal de TV.\n\nSi estás usando una antena inalámbrica, es posible que debas ajustar su ubicación o dirección para recibir la mayor cantidad de canales. Para obtener mejores resultados, colócala en un lugar alto y cerca de una ventana."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continuar"</item>
     <item msgid="235450158666155406">"Cancelar"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configuración del sintonizador de TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configuración del sintonizador de canales USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configuración del sintonizador de canales de red"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Este proceso podría demorar varios minutos"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"El sintonizador no está disponible en este momento o está grabando."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"No se encontraron canales"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"No se encontró ningún canal. Verifica que tu TV esté conectada a una fuente de señal de TV.\n\nSi usas una antena inalámbrica, ajusta su posición o dirección. Para obtener mejores resultados, ubícala en un lugar alto y cerca de una ventana. Luego, vuelve a hacer la búsqueda."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"No se encontraron canales en la búsqueda. Verifica que el sintonizador USB esté enchufado y conectado a una fuente de señal de TV.\n\nSi usas una antena inalámbrica, ajusta su ubicación o dirección. Para obtener mejores resultados, ubícala en un lugar alto y cerca de una ventana. Luego, vuelve a hacer la búsqueda."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"No se encontró ningún canal durante la búsqueda. Comprueba que el sintonizador de red esté encendido y conectado a una fuente de señal de TV.\n\nSi estás usando una antena inalámbrica, ajusta su ubicación o dirección. Para obtener mejores resultados, colócala en un lugar alto y cerca de una ventana, y repite la búsqueda."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Volver a buscar"</item>
     <item msgid="2092797862490235174">"Listo"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Busca canales de TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configuración del sintonizador de TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configuración del sintonizador de TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Se desconectó el sintonizador de TV USB."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Busca canales de TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configuración del sintonizador de TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configuración del sintonizador de TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configuración del sintonizador de TV de red"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Se desconectó el sintonizador de TV USB."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Se desconectó el sintonizador de red."</string>
 </resources>
diff --git a/usbtuner-res/values-es/strings.xml b/usbtuner-res/values-es/strings.xml
index e8e34cb..26742e6 100644
--- a/usbtuner-res/values-es/strings.xml
+++ b/usbtuner-res/values-es/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sintonizador de canales"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Sintonizador de canales USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Activar"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Desactivar"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Sintonizador de TV en red (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Espera hasta que finalice el procesamiento"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Selecciona la fuente de canales"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Sin señal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"No se ha podido sintonizar <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"No se podido sintonizar"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"El software del sintonizador se ha actualizado recientemente. Vuelve a buscar los canales."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Habilita el sonido envolvente en los ajustes del sistema de sonido para activar el audio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"No se puede reproducir el audio. Prueba con otra TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuración del sintonizador de canales"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configuración del sintonizador de canales"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configuración del sintonizador de canales USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configuración del sintonizador en red"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Comprueba que la TV esté conectada a una fuente de señal de TV.\n\n Si utilizas una antena inalámbrica, puede que tengas que cambiar su posición o dirección para recibir la mayor cantidad posible de canales. Para conseguir los mejores resultados, colócala en alto y cerca de una ventana."</string>
-    <string name="ut_setup_new_description" msgid="2610122936163002137">"Comprueba que el sintonizador USB esté enchufado y conectado a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, puede que tengas que cambiar su ubicación o dirección para recibir la mayor cantidad posible de canales. Para conseguir los mejores resultados, colócala en alto y cerca de una ventana."</string>
+    <string name="ut_setup_new_description" msgid="2610122936163002137">"Comprueba que el sintonizador USB esté enchufado y conectado a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, puede que tengas que cambiar su emplazamiento o dirección para recibir la mayor cantidad posible de canales. Para conseguir los mejores resultados, colócala en alto y cerca de una ventana."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Comprueba que el sintonizador en red esté encendido y conectado a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, es posible que tengas que cambiar su emplazamiento o su orientación para ver la mayoría de los canales. Para obtener los mejores resultados, colócala en un lugar alto cerca de una ventana."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continuar"</item>
     <item msgid="727245208787621142">"Ahora no"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"¿Quieres volver a ejecutar la configuración de canales?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Se quitarán los canales encontrados del sintonizador de canales y se volverán a buscar nuevos canales.\n\nComprueba que la TV esté conectada a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, puede que tengas que cambiar su posición o dirección para recibir la mayor cantidad posible de canales. Para conseguir los mejores resultados, colócala en alto y cerca de una ventana."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Se quitarán los canales encontrados con el sintonizador USB y se volverán a buscar nuevos canales.\n\nComprueba que el sintonizador USB esté enchufado y conectado a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, puede que tengas que cambiar su ubicación o dirección para recibir la mayor cantidad posible de canales. Para conseguir los mejores resultados, colócala en alto y cerca de una ventana."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Se quitarán los canales encontrados del sintonizador en red y se repetirá la búsqueda de canales.\n\nComprueba que el sintonizador en red esté encendido y conectado a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, es posible que tengas que cambiar su emplazamiento o su orientación para ver la mayoría de los canales. Para obtener los mejores resultados, colócala en un lugar alto cerca de una ventana."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continuar"</item>
     <item msgid="235450158666155406">"Cancelar"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configuración del sintonizador de canales"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configuración del sintonizador de canales USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configuración del sintonizador de canales en red"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Este proceso puede tardar varios minutos"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"El sintonizador no está disponible temporalmente o se está utilizando en otra grabación."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -75,13 +75,16 @@
   </string-array>
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"No se han encontrado canales"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"No se ha encontrado ningún canal. Comprueba que la TV esté conectada a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, cambia su posición o dirección. Para conseguir los mejores resultados, colócala en alto y cerca de una ventana. A continuación, vuelve a realizar la búsqueda."</string>
-    <string name="ut_result_not_found_description" msgid="1080746285957681414">"No se ha encontrado ningún canal. Comprueba que el sintonizador USB esté enchufado y conectado a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, cambia su ubicación o dirección. Para conseguir los mejores resultados, colócala en alto y cerca de una ventana. A continuación, vuelve a realizar la búsqueda."</string>
+    <string name="ut_result_not_found_description" msgid="1080746285957681414">"No se ha encontrado ningún canal. Comprueba que el sintonizador USB esté enchufado y conectado a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, cambia su emplazamiento o dirección. Para conseguir los mejores resultados, colócala en alto y cerca de una ventana. A continuación, vuelve a realizar la búsqueda."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"El análisis no ha encontrado ningún canal. Comprueba que el sintonizador en red esté encendido y conectado a una fuente de señal de TV.\n\nSi utilizas una antena inalámbrica, cambia su emplazamiento u orientación. Para obtener los mejores resultados, colócala en un lugar alto cerca de una ventana y repite el análisis."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Volver a buscar"</item>
     <item msgid="2092797862490235174">"Listo"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Busca canales de TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configuración del sintonizador de canales"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configuración de sintonizador de canales USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Sintonizador de canales USB desconectado."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Buscar canales de TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configuración del sintonizador de TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configuración de sintonizador de TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configuración del sintonizador de TV en red"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"El sintonizador de canales USB está desconectado."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"El sintonizador en red está desconectado."</string>
 </resources>
diff --git a/usbtuner-res/values-et/strings.xml b/usbtuner-res/values-et-rEE/strings.xml
similarity index 75%
rename from usbtuner-res/values-et/strings.xml
rename to usbtuner-res/values-et-rEE/strings.xml
index 70cb238..3d97a31 100644
--- a/usbtuner-res/values-et/strings.xml
+++ b/usbtuner-res/values-et-rEE/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Telerituuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-telerituuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Sees"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Väljas"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Teleri võrgutuuner (BEETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Oodake, kuni töötlemine on lõppenud"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Valige kanali allikas"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Pole signaali"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Kanalile <xliff:g id="CHANNEL_NAME">%s</xliff:g> häälestamine ebaõnnestus"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Häälestamine ebaõnnestus"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Tuuneri tarkvara värskendati hiljuti. Otsige kanaleid uuesti."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Heli lubamiseks lubage ruumiline heli süsteemi heliseadetes"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Heli ei saa esitada. Proovige teist telerit"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kanalituuneri seadistus"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Telerituuneri seadistus"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB-kanalituuneri seadistus"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Võrgutuuneri seadistus"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Veenduge, et teler oleks ühendatud teleri signaaliallikaga.\n\nKui kasutate õhuantenni, peate võimalikult paljude kanalite nägemiseks võib-olla kohandama selle asendit või suunda. Parimate tulemuste saavutamiseks asetage see kõrgele ja akna lähedale."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Veenduge, et USB-tuuner oleks pistikus ja ühendatud teleri signaaliallikaga.\n\nKui kasutate õhuantenni, peate enamiku kanalite nägemiseks võib-olla kohandama selle asendit või suunda. Parimate tulemuste saavutamiseks asetage see kõrgele ja akna lähedale."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Veenduge, et võrgutuuner oleks sisse lülitatud ja teleri signaaliallikaga ühendatud.\n\nKui kasutate õhuantenni, peate võib-olla muutma selle asendit või suunda, et rohkem kanaleid leida. Parimate tulemuste saavutamiseks asetage see kõrgesse kohta akna lähedale."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Jätka"</item>
     <item msgid="727245208787621142">"Mitte praegu"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Kas käitada kanali seadistust uuesti?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"See eemaldab telerituuneri leitud kanalid ja otsib uuesti uusi kanaleid.\n\nVeenduge, et teler oleks ühendatud teleri signaaliallikaga.\n\nKui kasutate õhuantenni, peate võimalikult paljude kanalite nägemiseks võib-olla kohandama selle asendit või suunda. Parimate tulemuste saavutamiseks asetage see kõrgele ja akna lähedale."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"See eemaldab USB-tuuneri leitud kanalid ja otsib uuesti uusi kanaleid.\n\nVeenduge, et USB-tuuner oleks pistikus ja ühendatud teleri signaaliallikaga.\n\nKui kasutate õhuantenni, peate enamiku kanalite nägemiseks võib-olla kohandama selle asendit või suunda. Parimate tulemuste saavutamiseks asetage see kõrgele ja akna lähedale."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"See eemaldab võrgutuunerist leitud kanalid ja skannib uuesti uusi kanaleid.\n\nVeenduge, et võrgutuuner oleks sisse lülitatud ja teleri signaaliallikaga ühendatud.\n\nKui kasutate õhuantenni, peate võib-olla muutma selle asendit või suunda, et rohkem kanaleid leida. Parimate tulemuste saavutamiseks asetage see kõrgesse kohta akna lähedale."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Jätka"</item>
     <item msgid="235450158666155406">"Tühista"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Telerituuneri seadistus"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB-kanalituuneri seadistus"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Võrgutuuneri kanalite seadistus"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"See võib võtta mitu minutit"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuuner pole ajutiselt saadaval või seda kasutatakse juba salvestamiseks."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Ühtegi kanalit ei leitud"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Otsimisel ei leitud ühtegi kanalit. Veenduge, et teler oleks ühendatud teleri signaaliallikaga.\n\nKui kasutate õhuantenni, kohandage selle asendit või suunda. Parimate tulemuste saavutamiseks asetage see kõrgele ja akna lähedale ning otsige uuesti."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Otsimisel ei leitud ühtegi kanalit. Veenduge, et USB-tuuner oleks pistikus ja ühendatud teleri signaaliallikaga.\n\nKui kasutate õhuantenni, kohandage selle asendit või suunda. Parimate tulemuste saavutamiseks asetage see kõrgele ja akna lähedale ning otsige uuesti."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Skannimisel ei leitud ühtegi kanalit. Veenduge, et võrgutuuner oleks sisse lülitatud ja teleri signaaliallikaga ühendatud.\n\nKui kasutate õhuantenni, muutke selle asendit või suunda. Parimate tulemuste saavutamiseks asetage see kõrgesse kohta akna lähedale ja skannige uuesti."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Otsi uuesti"</item>
     <item msgid="2092797862490235174">"Valmis"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Otsige telekanaleid"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Telerituuneri seadistus"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB-telerituuneri seadistus"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-telerituuner eemaldati."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Telekanalite otsimine"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Telerituuneri seadistus"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB-telerituuneri seadistus"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Teleri võrgutuuneri seadistus"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-telerituuner eemaldati."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Võrgutuuner eemaldati."</string>
 </resources>
diff --git a/usbtuner-res/values-eu/strings.xml b/usbtuner-res/values-eu-rES/strings.xml
similarity index 73%
rename from usbtuner-res/values-eu/strings.xml
rename to usbtuner-res/values-eu-rES/strings.xml
index a0d456e..0f7ac94 100644
--- a/usbtuner-res/values-eu/strings.xml
+++ b/usbtuner-res/values-eu-rES/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sintonizadorea"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB bidezko sintonizadorea"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Aktibatuta"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Desaktibatuta"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Sareko sintonizadorea (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Itxaron prozesatzen amaitu arte"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Hautatu kanalaren iturburua"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Ez dago seinalerik"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Ezin izan da sintonizatu <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Ezin izan da sintonizatu"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Sintonizadorearen softwarea berriki eguneratu da. Bilatu kanalak berriro."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Audioa gaitzeko, joan sistemaren soinuaren ezarpenetara eta gaitu soinu inguratzailea"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Ezin da erreproduzitu audioa. Saiatu beste telebista batean."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kanal-sintonizadorearen konfigurazioa"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Sintonizadorearen konfigurazioa"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB kanal-sintonizadorearen konfigurazioa"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Sareko sintonizadorearen konfigurazioa"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Egiaztatu telebista-seinalearen iturburu batera konektatuta dagoela telebista.\n\nAntena analogiko bat badarabilzu, agian bere kokapena edo norabidea doitu beharko dituzu kanal gehienak eskuratzeko. Emaitzarik onenak lortzeko, ezarri toki altu batean edo leiho baten ondoan."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Egiaztatu USB sintonizadorea entxufatuta eta telebistako seinale-iturburu batera konektatuta dagoela.\n\nHari gabeko antena badarabilzu, doitu bere kokapena edo norabidea. Emaitzarik onenak lortzeko, ezarri toki altu batean edo leiho baten ondoan eta gauzatu bilaketa berriro."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Egiaztatu sintonizadorea piztuta dagoela eta telebista-seinalea igortzen duen iturburu batera konektatu duzula.\n\nHari-gabeko antena bat erabiltzen ari bazara, doi ezazu haren kokapena edo norabidea ahal bezain beste kanal aurkitzeko. Emaitzarik onenak lortzeko, ezar ezazu ahal bezain altu eta leiho batetik gertu."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Jarraitu"</item>
     <item msgid="727245208787621142">"Orain ez"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Berriro konfiguratu nahi dituzu kanalak?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Sintonizadoreak aurkitutako kanalak kenduko dira eta berriro bilatuko dira kanalak.\n\nEgiaztatu telebista-seinalearen iturburu batera konektatuta dagoela telebista.\n\nAntena analogiko bat badarabilzu, agian bere kokapena edo norabidea doitu beharko dituzu kanal gehienak eskuratzeko. Emaitzarik onenak lortzeko, ezarri toki altu batean edo leiho baten ondoan."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"USB sintonizadoreak aurkitutako kanalak kenduko dira eta berriro bilatuko dira kanalak.\n\nEgiaztatu USB sintonizadorea entxufatuta eta telebistako seinale-iturburu batera konektatuta dagoela.\n\nAntena analogiko bat badarabilzu, agian bere kokapena edo norabidea doitu beharko dituzu kanal gehienak eskuratzeko. Emaitzarik onenak lortzeko, ezarri toki altu batean edo leiho baten ondoan."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Hori eginez gero, kendu egingo dira sareko sintonizadoreak aurkitutako kanalak eta zerotik hasiko da berriro kanalak bilatzen.\n\n Egiaztatu sintonizadorea piztuta dagoela eta telebista-seinalea igortzen duen iturburu batera konektatu duzula.\n\nHari-gabeko antena bat erabiltzen ari bazara, doi ezazu haren kokapena edo norabidea ahal bezain beste kanal aurkitzeko. Emaitzarik onenak lortzeko, ezar ezazu ahal bezain altu eta leiho batetik gertu."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Jarraitu"</item>
     <item msgid="235450158666155406">"Utzi"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Sintonizadorearen konfigurazioa"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB kanal-sintonizadorearen konfigurazioa"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Sareko kanalen sintonizadorearen konfigurazioa"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Zenbait minutu beharko dira"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Sintonizadorea ez dago erabilgarri edo beste zerbait ari da grabatzen."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Ez da aurkitu kanalik"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Bilaketak ez du aurkitu kanalik. Egiaztatu telebista-seinalearen iturburu batera konektatuta dagoela telebista.\n\nAntena analogiko bat badarabilzu, doitu bere kokapena edo norabidea. Emaitzarik onenak lortzeko, ezarri toki altu batean edo leiho baten ondoan eta gauzatu bilaketa berriro."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Bilaketak ez du aurkitu kanalik. Egiaztatu USB sintonizadorea entxufatuta eta telebistako seinale-iturburu batera konektatuta dagoela.\n\nAntena analogiko bat badarabilzu, doitu bere kokapena edo norabidea. Emaitzarik onenak lortzeko, ezarri toki altu batean edo leiho baten ondoan eta gauzatu bilaketa berriro."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Ez da aurkitu kanalik. Egiaztatu sintonizadorea piztuta dagoela eta telebista-seinalea igortzen duen iturburu batera konektatu duzula.\n\nHari-gabeko antena bat erabiltzen ari bazara, doi ezazu haren kokapena edo norabidea. Emaitzarik onenak lortzeko, ezar ezazu ahal bezain altu eta leiho batetik gertu. Ondoren, bila itzazu kanalak berriro."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Bilatu berriro"</item>
     <item msgid="2092797862490235174">"Eginda"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Bilatu telebista-kanalak"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Sintonizadorearen konfigurazioa"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB bidezko sintonizadorearen konfigurazioa"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB bidezko sintonizadorea deskonektatu da."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Bilatu telebista-kateak"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Sintonizadorearen konfigurazioa"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB bidezko sintonizadorearen konfigurazioa"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Sareko sintonizadorearen konfigurazioa"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Deskonektatu da USB bidezko sintonizadorea."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Deskonektatu da sareko sintonizadorea."</string>
 </resources>
diff --git a/usbtuner-res/values-fa/strings.xml b/usbtuner-res/values-fa/strings.xml
index 8a51a4f..586fc92 100644
--- a/usbtuner-res/values-fa/strings.xml
+++ b/usbtuner-res/values-fa/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"تنظیم‌کننده تلویزیون"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"‏تنظیم‌کننده تلویزیون USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"روشن"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"خاموش"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"تنظیم‌کننده تلویزیون شبکه (بتا)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"لطفاً تا پایان پردازش صبر کنید"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"منبع کانال را انتخاب کنید"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"بدون سیگنال"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"تنظیم به <xliff:g id="CHANNEL_NAME">%s</xliff:g> انجام نشد"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"تنظیم ناموفق بود"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"نرم‌افزار تنظیم‌کننده اخیراً به‌روزرسانی شده است. لطفاً کانال‌ها را دوباره اسکن کنید."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"برای فعال کردن صدا، صدای فراگیر را در تنظیمات صدای سیستم فعال کنید"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"صوت پخش نمی‌شود. لطفاً تلویزیون دیگری را امتحان کنید."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"راه‌اندازی تنظیم‌کننده کانال"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"راه‌اندازی تنظیم‌کننده تلویزیون"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"‏راه‌اندازی تنظیم‌کننده کانال USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"راه‌اندازی تنظیم‌کننده شبکه‌ای"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"مطمئن شوید تلویزیونتان به منبع سیگنال تلویزیونی متصل است.\n\nدر صورت استفاده از آنتن بی‌سیم شاید لازم باشد برای دریافت کانال‌های بیشتر، موقعیت یا جهت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"‏مطمئن شوید تنظیم‌کننده USB به منبع نیرو و منبع سیگنال تلویزیونی متصل است.\n\nدر صورت استفاده از آنتن بی‌سیم، موقعیت یا جهت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"مطمئن شوید تنظیم‌کننده شبکه‌ای به برق و منبع سیگنال تلویزیونی وصل است.\n\nاگر از آنتن هوایی استفاده می‌کنید، ممکن است لازم باشد برای دریافت بیشترین تعداد کانال مکان و موقعیت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"ادامه"</item>
     <item msgid="727245208787621142">"فعلاً نه"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"تنظیم کانال دوباره اجرا شود؟"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"با این کار کانال‌های پیداشده از تنظیم‌کننده تلویزیون حذف می‌شوند و دوباره برای کانال‌های جدید اسکن می‌کند.\n\nمطمئن شوید تلویزیونتان به منبع سیگنال تلویزیونی متصل است.\n\nدر صورت استفاده از آنتن بی‌سیم، شاید لازم باشد برای دریافت کانال‌های بیشتر، موقعیت یا جهت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"‏این کار کانال‌های پیداشده از تنظیم‌کننده USB را حذف می‌کند و دوباره کانال‌های جدید را اسکن می‌کند.\n\nمطمئن شوید تنظیم‌کننده USB به منبع نیرو و منبع سیگنال تلویزیونی متصل است.\n\nدر صورت استفاده از آنتن بی‌سیم، برای دریافت کانال‌های بیشتر، موقعیت یا جهت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید و دوباره اسکن کنید."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"این کار کانال‌های پیداشده را از تنظیم‌کننده شبکه‌ای حذف می‌کند و دوباره کانال‌های جدید را اسکن می‌کند.\n\nمطمئن شوید تنظیم‌کننده شبکه‌ای به برق و منبع سیگنال تلویزیونی وصل است.\n\nاگر از آنتن هوایی استفاده می‌کنید، ممکن است لازم باشد برای دریافت بیشترین تعداد کانال مکان و موقعیت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"ادامه"</item>
     <item msgid="235450158666155406">"لغو"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"راه‌اندازی تنظیم‌کننده تلویزیون"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"‏راه‌اندازی تنظیم‌کننده کانال USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"راه‌اندازی تنظیم‌کننده کانال شبکه‌ای"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"ممکن است چند دقیقه طول بکشد"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"تنظیم‌کننده موقتاً دردسترس نیست یا در این لحظه در ضبط شدن استفاده می‌شود."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"کانالی پیدا نشد"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"اسکن هیچ کانالی پیدا نکرد. مطمئن شوید تلویزیونتان به یک منبع سیگنال تلویزیونی متصل است. \n\nدر صورت استفاده از آنتن بی‌سیم، موقعیت یا جهت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید و دوباره اسکن کنید."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"‏اسکن هیچ کانالی پیدا نکرد. مطمئن شوید تنظیم‌کننده USB به منبع نیرو و منبع سیگنال تلویزیونی متصل است.\n\nدر صورت استفاده از آنتن بی‌سیم، موقعیت یا جهت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید و دوباره اسکن کنید."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"اسکن، کانالی پیدا نکرد. مطمئن شوید تنظیم‌کننده شبکه‌ای به برق و منبع سیگنال تلویزیونی وصل است.\n\nاگر از آنتن هوایی استفاده می‌کنید، موقعیت یا جهت آن را تنظیم کنید. برای بهترین نتایج، آن را در جای بلند و نزدیک پنجره قرار دهید و دوباره اسکن کنید."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"اسکن دوباره"</item>
     <item msgid="2092797862490235174">"تمام"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"اسکن کانال‌های تلویزیون"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"راه‌اندازی تنظیم‌کننده تلویزیون"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"‏راه‌اندازی تنظیم‌کننده تلویزیون USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"‏تیونر تلویزیون USB  قطع شد."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"اسکن کانال‌های تلویزیون"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"راه‌اندازی تنظیم‌کننده تلویزیون"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"‏راه‌اندازی تنظیم‌کننده تلویزیون USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"راه‌اندازی تنظیم‌کننده تلویزیون شبکه‌ای"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"‏ارتباط تیونر USB تلویزیون قطع شد."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"ارتباط تیونر شبکه قطع شد."</string>
 </resources>
diff --git a/usbtuner-res/values-fi/strings.xml b/usbtuner-res/values-fi/strings.xml
index 79d0c7f..4dabc97 100644
--- a/usbtuner-res/values-fi/strings.xml
+++ b/usbtuner-res/values-fi/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV-viritin"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-TV-viritin"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Ota käyttöön"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Poista käytöstä"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Antenni-TV-viritin (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Odota, että käsittely on valmis."</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Valitse kanavalähde."</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Ei signaalia"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Kanavan <xliff:g id="CHANNEL_NAME">%s</xliff:g> virittäminen epäonnistui."</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Virittäminen epäonnistui."</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Viritinohjelmisto on päivitetty äskettäin. Hae kanavat uudelleen."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Ota ääni käyttöön kytkemällä tilaääni päälle järjestelmän ääniasetuksissa."</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Äänen toistaminen ei onnistu. Yritä käyttää toista TV:tä."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kanavavirittimen määritys"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV-virittimen määritys"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB-kanavavirittimen määritys"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Antennivirittimen määritys"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Tarkista, että TV on liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, useampien kanavien löytäminen saattaa edellyttää sen paikan tai suuntauksen säätämistä. Saat parhaan tuloksen asettamalla antennin korkealle ja lähelle ikkunaa."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Tarkista, että USB-viritin on kytketty oikein ja liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, useampien kanavien löytäminen saattaa edellyttää sen paikan ja suuntauksen säätämistä. Saat parhaan tuloksen asettamalla antennin korkealle ja lähelle ikkunaa."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Tarkista, että viritin on päällä ja liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, säädä sen paikkaa tai suuntausta. Aseta antenni korkealle ja lähelle ikkunaa, jotta saat parhaat tulokset, ja tee uusi haku."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Jatka"</item>
     <item msgid="727245208787621142">"Ei nyt"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Haetaanko kanavia uudelleen?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Tämä poistaa TV-virittimen löytämät kanavat ja tekee kanavahaun uudelleen.\n\nTarkista, että TV on liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, useampien kanavien löytäminen saattaa edellyttää sen paikan tai suuntauksen säätämistä. Saat parhaan tuloksen asettamalla antennin korkealle ja lähelle ikkunaa."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Tämä poistaa USB-virittimen löytämät kanavat ja tekee kanavahaun uudelleen.\n\nTarkista, että USB-viritin on kytketty oikein ja liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, useampien kanavien löytäminen saattaa edellyttää sen paikan tai suuntauksen säätämistä. Saat parhaan tuloksen asettamalla antennin korkealle ja lähelle ikkunaa."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Tämä poistaa virittimen löytämät kanavat ja etsii kanavia uudestaan.\n\nTarkista, että viritin on päällä ja liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, säädä sen paikkaa tai suuntausta. Aseta antenni korkealle ja lähelle ikkunaa, jotta saat parhaat tulokset, ja tee uusi haku."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Jatka"</item>
     <item msgid="235450158666155406">"Peruuta"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV-virittimen määritys"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB-kanavavirittimen määritys"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Antennikanavavirittimen määritys"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Tämä voi kestää useita minuutteja."</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Viritin ei ole toistaiseksi käytettävissä tai se on nauhoitteen käytössä."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Kanavia ei löytynyt"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Haku ei löytänyt yhtään kanavaa. Tarkista, että TV on liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, säädä sen paikkaa tai suuntausta. Saat parhaan tuloksen asettamalla antennin korkealle ja lähelle ikkunaa. Tee haku sitten uudelleen."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Haku ei löytänyt yhtään kanavaa. Tarkista, että USB-viritin on kytketty oikein ja liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, säädä sen paikkaa tai suuntausta. Saat parhaan tuloksen asettamalla antennin korkealle ja lähelle ikkunaa. Tee haku sitten uudelleen."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Haussa ei löytynyt kanavia. Tarkista, että viritin on päällä ja liitetty TV-signaalilähteeseen.\n\nJos käytät antennia, säädä sen paikkaa tai suuntausta. Aseta antenni korkealle ja lähelle ikkunaa, jotta saat parhaat tulokset, ja tee uusi haku."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Hae uudelleen"</item>
     <item msgid="2092797862490235174">"Valmis"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Hae TV-kanavia"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV-virittimen määritys"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB-TV-virittimen määritys"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-TV-viritin ei ole kytketty"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Hae TV-kanavia"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV-virittimen määritys"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB-TV-virittimen määritys"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Antenni-TV-virittimen määritys"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-TV-viritin ei ole kytketty."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Verkkoviritin ei ole kytketty."</string>
 </resources>
diff --git a/usbtuner-res/values-fr-rCA/strings.xml b/usbtuner-res/values-fr-rCA/strings.xml
index 54e8759..754649a 100644
--- a/usbtuner-res/values-fr-rCA/strings.xml
+++ b/usbtuner-res/values-fr-rCA/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Syntoniseur télé"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Syntoniseur télé USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Activer"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Désactivé"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Syntoniseur télé réseau (BÊTA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Veuillez patienter jusqu\'à la fin du traitement"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Sélectionnez votre source de chaînes"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Aucun signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Impossible de syntoniser <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Échec de syntonisation"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Le logiciel du syntoniseur a été mis à jour récemment. Veuillez rechercher les chaînes à nouveau."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Pour activer l\'audio, vous devez activer le son ambiophonique dans les paramètres sonores du système"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Impossible de lire l\'audio. Veuillez essayer sur un autre téléviseur."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuration du syntoniseur de chaînes"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configuration du syntoniseur télé"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configurer les chaînes du syntoniseur USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configuration du syntoniseur réseau"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Vérifiez que le téléviseur est connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne, vous devrez peut-être ajuster sa position ou son orientation pour recevoir le plus de chaînes possible. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Vérifiez que le syntoniseur USB est branché et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne, ajustez sa position ou son orientation. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre, puis relancez la recherche."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Assurez-vous que le syntoniseur réseau est allumé et connecté à une source de signal télé.\n\nSi vous utilisez une antenne, il se peut que vous deviez ajuster sa position ou sa direction pour capter un maximum de chaînes. Pour obtenir des résultats optimaux, placez-la en hauteur et près d\'une fenêtre."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continuer"</item>
     <item msgid="727245208787621142">"Pas maintenant"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Relancer la configuration de la chaîne?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Cette opération permet de supprimer les chaînes détectées du syntoniseur télé et d\'en rechercher de nouvelles.\n\nVérifiez que le téléviseur est connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne, vous devrez peut-être ajuster sa position ou son orientation pour recevoir le plus de chaînes possible. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Cette opération permet de supprimer les chaînes détectées du syntoniseur USB et d\'en rechercher de nouvelles.\n\nVérifiez que le syntoniseur USB est branché et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne, vous devrez peut-être ajuster sa position ou son orientation pour recevoir le plus de chaînes possible. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Cela supprimera les chaînes trouvées du syntoniseur réseau et lancera une nouvelle recherche.\n\nAssurez-vous que le syntoniseur réseau est allumé et connecté à une source de signal télé.\n\nSi vous utilisez une antenne, il se peut que vous deviez ajuster sa position ou sa direction pour capter un maximum de chaînes. Pour obtenir des résultats optimaux, placez-la en hauteur et près d\'une fenêtre."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continuer"</item>
     <item msgid="235450158666155406">"Annuler"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configuration du syntoniseur télé"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configurer les chaînes du syntoniseur USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configuration du syntoniseur de chaînes réseau"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Cela peut prendre plusieurs minutes"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Le syntoniseur n\'est pas accessible ou bien il est en cours d\'utilisation par l\'enregistreur."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Aucune chaîne"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"La recherche n\'a détecté aucune chaîne. Vérifiez que le téléviseur est connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne, ajustez sa position ou son orientation. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre, puis relancez la recherche."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"La recherche n\'a détecté aucune chaîne. Vérifiez que le syntoniseur USB est branché et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne, ajustez sa position ou son orientation. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre, puis relancez la recherche."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"La recherche n\'a détecté aucune chaîne. Assurez-vous que le syntoniseur réseau est allumé et connecté à une source de signal télé.\n\nSi vous utilisez une antenne, ajustez sa position ou sa direction. Pour obtenir des résultats optimaux, placez-la en hauteur et près d\'une fenêtre, puis relancez la recherche."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Rechercher à nouveau"</item>
     <item msgid="2092797862490235174">"Terminé"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Rechercher les chaînes de télévision"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configuration du syntoniseur télé"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configurer le syntoniseur télé USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Le syntoniseur télé USB est débranché."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Rechercher les chaînes de télévision"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configuration du syntoniseur télé"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configurer le syntoniseur télé USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configuration du syntoniseur télé réseau"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Le syntoniseur télé USB est déconnecté."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Le syntoniseur réseau est déconnecté."</string>
 </resources>
diff --git a/usbtuner-res/values-fr/strings.xml b/usbtuner-res/values-fr/strings.xml
index 4cb551f..3b4a658 100644
--- a/usbtuner-res/values-fr/strings.xml
+++ b/usbtuner-res/values-fr/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Tuner TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Tuner TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Activé"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Désactivé"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Tuner TV réseau (VERSION BÊTA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Veuillez patienter jusqu\'à la fin du traitement."</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Sélectionnez la source de la chaîne."</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Aucun signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Échec de sélection de la chaîne <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Échec de la sélection de la chaîne"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Le logiciel du tuner a été mis à jour récemment. Veuillez lancer une nouvelle recherche des chaînes."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Activer le son surround dans les paramètres sonores du système pour activer l\'audio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Impossible de lire le fichier audio. Veuillez utiliser un autre téléviseur"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuration du tuner de chaînes"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configuration du tuner TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configuration du tuner de chaînes USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configuration du tuner réseau"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Vérifiez que le téléviseur est connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, vous devrez peut-être ajuster sa position ou son orientation pour recevoir le plus de chaînes possible. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Vérifiez que le tuner USB est branché et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, ajustez sa position ou son orientation. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre, puis relancez la recherche."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Vérifiez que le tuner réseau est allumé et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, vous devrez peut-être ajuster sa position ou son orientation pour recevoir le plus de chaînes possible. Pour de meilleurs résultats, placez-la en hauteur et près d\'une fenêtre."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continuer"</item>
     <item msgid="727245208787621142">"Pas maintenant"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Relancer la configuration de la chaîne ?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Cette opération permet de supprimer les chaînes détectées du tuner TV et d\'en rechercher de nouvelles.\n\nVérifiez que le téléviseur est connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, vous devrez peut-être ajuster sa position ou son orientation pour recevoir le plus de chaînes possible. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Cette opération permet de supprimer les chaînes détectées du tuner USB et d\'en rechercher de nouvelles.\n\nVérifiez que le tuner USB est branché et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, vous devrez peut-être ajuster sa position ou son orientation pour recevoir le plus de chaînes possible. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Cette opération permet de supprimer les chaînes détectées du tuner réseau et d\'en rechercher de nouvelles.\n\nVérifiez que le tuner réseau est allumé et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, vous devrez peut-être ajuster sa position ou son orientation pour recevoir le plus de chaînes possible. Pour de meilleurs résultats, placez-la en hauteur et près d\'une fenêtre."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continuer"</item>
     <item msgid="235450158666155406">"Annuler"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configuration du tuner TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configuration du tuner de chaînes USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configuration du tuner de chaînes réseau"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Cette opération peut prendre plusieurs minutes."</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Le tuner est temporairement indisponible ou est déjà utilisé pour l\'enregistrement."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Aucune chaîne n\'a été détectée"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"La recherche n\'a détecté aucune chaîne. Vérifiez que le téléviseur est connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, ajustez sa position ou son orientation. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre, puis relancez la recherche."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"La recherche n\'a détecté aucune chaîne. Vérifiez que le tuner USB est branché et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, ajustez sa position ou son orientation. Pour obtenir les meilleurs résultats, placez-la dans une position élevée et près d\'une fenêtre, puis relancez la recherche."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"La recherche n\'a détecté aucune chaîne. Vérifiez que le tuner réseau est allumé et connecté à la source d\'un signal de télévision.\n\nSi vous utilisez une antenne Over The Air, ajustez sa position ou son orientation. Pour de meilleurs résultats, placez-la en hauteur et près d\'une fenêtre, puis relancez la recherche."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Rechercher à nouveau"</item>
     <item msgid="2092797862490235174">"OK"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Rechercher les chaînes de télévision"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configuration du tuner TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configuration du tuner TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Le tuner TV USB est déconnecté."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Rechercher les chaînes de télévision"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configuration du tuner TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configuration du tuner TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configuration du tuner TV réseau"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Le tuner TV USB est déconnecté."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Tuner réseau déconnecté."</string>
 </resources>
diff --git a/usbtuner-res/values-gl/strings.xml b/usbtuner-res/values-gl-rES/strings.xml
similarity index 74%
rename from usbtuner-res/values-gl/strings.xml
rename to usbtuner-res/values-gl-rES/strings.xml
index 58c1460..4c75fc6 100644
--- a/usbtuner-res/values-gl/strings.xml
+++ b/usbtuner-res/values-gl-rES/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sintonizador de televisión"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Sintonizador USB de televisión"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Activar"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Desactivar"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Sintonizador de televisión de rede (beta)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Espera a que finalice o procesamento"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Selecciona a fonte da túa canle"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Sen sinal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Produciuse un erro ao sintonizar <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Produciuse un erro ao sintonizar"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"O software do sintonizador actualizouse recentemente. Volve buscar canles."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Activa o son envolvente na configuración de son do sistema para activar o audio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Non se pode reproducir o audio. Proba con outra televisión"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuración do sintonizador de canles"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configuración do sintonizador de televisión"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configuración do sintonizador de canles USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configuración do sintonizador de rede"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Comproba que a televisión está conectada a unha fonte de sinal de televisión.\n\nSe usas unha antena sen fíos, é posible que teñas que axustar a súa posición ou dirección para recibir a maioría das canles. Para conseguir os mellores resultados, colócaa nun lugar alto e preto dunha ventá."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Comproba que o sintonizador USB está enchufado e conectado a unha fonte de sinal de televisión.\n\nSe usas unha antena sen fíos, é posible que teñas que axustar a súa posición ou dirección para recibir a maioría das canles. Para conseguir os mellores resultados, colócaa nun lugar alto e preto dunha ventá."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Verifica que o sintonizador de rede estea acendido e conectado a unha fonte de sinal de televisión.\n\nSe usas unha antena sen fíos, é posible que teñas que axustar a súa posición ou dirección para recibir a maioría das canles. Para conseguir os mellores resultados, colócaa nun lugar alto e preto dunha ventá."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continuar"</item>
     <item msgid="727245208787621142">"Agora non"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Queres volver executar a configuración da canle?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Esta acción eliminará as canles que atopaches co sintonizador de televisión e buscará outras novas.\n\nComproba que a televisión está conectada a unha fonte de sinal de televisión.\n\nSe usas unha antena sen fíos, é posible que teñas que axustar a súa posición ou dirección para recibir a maioría das canles. Para conseguir os mellores resultados, colócaa nun lugar alto e preto dunha ventá."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Esta acción eliminará as canles que atopaches co sintonizador USB e buscará outras novas.\n\nComproba que o sintonizador USB está enchufado e conectado a unha fonte de sinal de televisión.\n\nSe usas unha antena sen fíos, é posible que teñas que axustar a súa posición ou dirección para recibir a maioría das canles. Para conseguir os mellores resultados, colócaa nun lugar alto e preto dunha ventá."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Con esta acción quitaranse as canles atopadas do teu sintonizador de rede e buscaranse novas canles outra vez.\n\nVerifica que o sintonizador de rede estea acendido e conectado a unha fonte de sinal de televisión.\n\n}Se usas unha antena sen fíos, é posible que teñas que axustar a súa posición ou dirección para recibir a maioría das canles. Para conseguir os mellores resultados, colócaa nun lugar alto e preto dunha ventá."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continuar"</item>
     <item msgid="235450158666155406">"Cancelar"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configuración do sintonizador de televisión"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configuración do sintonizador de canles USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configuración do sintonizador de canles de rede"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Esta acción pode tardar varios minutos"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"O sintonizador non está dispoñible temporalmente ou xa se utiliza para unha gravación."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Non se atopou ningunha canle"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Durante a busca non se atopou ningunha canle. Comproba que a televisión está conectada a unha fonte de sinal de televisión.\n\nSe usas unha antena sen fíos, axusta a súa posición ou dirección. Para conseguir os mellores resultados, colócaa nun lugar alto, preto dunha ventá e realiza a fai a busca de novo."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"A busca non atopou ningunha canle. Comproba que o sintonizador USB está enchufado e conectado a unha fonte de sinal de televisión.\n\nSe usas unha antena sen fíos, axusta a súa posición ou dirección. Para conseguir os mellores resultados, colócaa nun lugar alto, preto dunha ventá e realiza a busca de novo."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"A busca de canles non obtivo resultados. Verifica que o sintonizador de rede estea acendido e conectado a unha fonte de sinal de televisión.\n\nSe usas unha antena sen fíos, axusta a súa posición ou dirección. Para conseguir os mellores resultados, colócaa nun lugar alto, preto dunha ventá, e realiza a busca de novo."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Buscar de novo"</item>
     <item msgid="2092797862490235174">"Feito"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Busca canles de televisión"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configuración do sintonizador de televisión"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configuración do sintonizador USB de televisión"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Desconectouse o sintonizador de televisión USB."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Buscar canles de televisión"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configuración do sintonizador de televisión"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configuración do sintonizador USB de televisión"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configuración do sintonizador de televisión de rede"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Desconectouse o sintonizador de televisión USB."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Desconectouse o sintonizador de rede."</string>
 </resources>
diff --git a/usbtuner-res/values-hi/strings.xml b/usbtuner-res/values-hi/strings.xml
index ea0d51c..265670e 100644
--- a/usbtuner-res/values-hi/strings.xml
+++ b/usbtuner-res/values-hi/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"टीवी ट्यूनर"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB टीवी ट्यूनर"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"चालू करें"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"बंद करें"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"नेटवर्क टीवी ट्यूनर (बीटा)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"कृपया प्रक्रिया पूरी होने का इंतज़ार करें"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"अपना चैनल स्रोत चुनें"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"कोई सिग्नल नहीं"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> को ट्यून करने में विफल रहा"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ट्यून करने में विफल रहा"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ट्यूनर सॉफ़्टवेयर को हाल ही में अपडेट किया गया है. कृपया चैनलों के लिए दोबारा स्कैन करें."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ऑडियो सक्षम करने के लिए सिस्टम साउंड सेटिंग में सराउंड साउंड सक्षम करें"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"ऑडियो नहीं चल पा रहा है. कृपया कोई दूसरा टीवी आज़माएं"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"चैनल ट्यूनर सेटअप"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"टीवी ट्यूनर सेटअप"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB चैनल ट्यूनर सेटअप"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"नेटवर्क ट्यूनर सेटअप"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"पुष्टि करें कि आपका टीवी किसी टीवी सिग्नल स्रोत से कनेक्ट किया हुआ है.\n\nयदि ओवर द एयर एंटेना का उपयोग कर रहे हैं, तो अधिकांश चैनल पाने के लिए आपको उसकी स्थिति या दिशा समायोजित करने की आवश्यकता हो सकती है. सबसे अच्छे परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास लगाएं."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"पुष्टि करें कि USB ट्यूनर प्लग इन है और टीवी सिग्नल स्रोत से कनेक्ट किया हुआ है.\n\nयदि आप ओवर द एयर एंटेना का उपयोग कर रहे हैं, तो अधिकांश चैनल पाने के लिए आपको उसकी स्थिति या दिशा समायोजित करने की आवश्यकता हो सकती है. अच्छे परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास लगाएं."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"सत्यापित करें कि नेटवर्क ट्यूनर चालू है और किसी टीवी सिग्नल स्रोत से कनेक्ट है.\n\nयदि किसी ओवर-द-एयर एंटेना का उपयोग कर रहे हैं, तो अधिकांश चैनल प्राप्त करने के लिए आपको एंटेना का स्थान या दिशा समायोजित करनी पड़ सकती है. सर्वश्रेष्ठ परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास रखें."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"जारी रखें"</item>
     <item msgid="727245208787621142">"अभी नहीं"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"चैनल सेटअप फिर से चलाएं?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"इससे टीवी ट्यूनर से मिले चैनल निकल जाएंगे और नए चैनल दोबारा स्कैन किए जाएंगे.\n\nपुष्टि करें कि आपका टीवी किसी टीवी सिग्नल स्रोत से कनेक्ट किया हुआ है.\n\nयदि ओवर द एयर एंटेना का उपयोग कर रहे हैं, तो अधिकांश चैनल पाने के लिए आपको उसकी स्थिति या दिशा समायोजित करने की आवश्यकता हो सकती है. सबसे अच्छे परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास लगाएं."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"इससे USB ट्यूनर से मिले चैनल निकल जाएंगे और नए चैनलों के लिए फिर से स्कैन किया जाएगा.\n\nपुष्टि करें कि USB ट्यूनर प्लग इन है और टीवी सिग्नल स्रोत से कनेक्ट किया हुआ है.\n\nयदि आप ओवर द एयर एंटेना का उपयोग कर रहे हैं, तो अधिकांश चैनल पाने के लिए आपको उसकी स्थिति या दिशा समायोजित करने की आवश्यकता हो सकती है. अच्छे परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास लगाएं."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"ऐसा करने से नेटवर्क ट्यूनर से मिले चैनल निकाल दिए जाएंगे और नए चैनल के लिए फिर से स्कैन किया जाएगा.\n\nसत्यापित करें कि नेटवर्क ट्यूनर चालू है और किसी टीवी सिग्नल स्रोत से कनेक्ट है.\n\nयदि किसी ओवर-द-एयर एंटेना का उपयोग कर रहे हैं, तो अधिकांश चैनल प्राप्त करने के लिए आपको एंटेना का स्थान या दिशा समायोजित करनी पड़ सकती है. सर्वश्रेष्ठ परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास रखें."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"जारी रखें"</item>
     <item msgid="235450158666155406">"रद्द करें"</item>
@@ -54,8 +53,9 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"टीवी ट्यूनर सेटअप"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB चैनल ट्यूनर सेटअप"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"नेटवर्क चैनल ट्यूनर सेटअप"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"इसमें कुछ मिनट लग सकते हैं"</string>
-    <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ट्यूनर अस्थायी रूप से उपलब्ध नहीं है या रिकॉर्डिंग में उसका उपयोग पहले ही कर लिया गया है."</string>
+    <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ट्यूनर अस्थायी रूप से उपलब्ध नहीं है या रिकॉर्डिंग में उसका उपयोग पहले ही हो रहा है."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
       <item quantity="one">%1$d चैनल मिले</item>
       <item quantity="other">%1$d चैनल मिले</item>
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"कोई चैनल नहीं मिला"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"स्कैन करने से कोई भी चैनल नहीं मिला. पुष्टि करें कि आपका टीवी किसी टीवी सिग्नल स्रोत से कनेक्ट किया हुआ है.\n\nयदि ओवर द एयर एंटेना का उपयोग कर रहे हैं, तो उसकी स्थिति या दिशा समायोजित करें. सबसे अच्छे परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास लगाएं और दोबारा स्कैन करें."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"स्कैन करने से कोई चैनल नहीं मिला. पुष्टि करें कि USB ट्यूनर प्लग इन है और टीवी सिग्नल स्रोत से कनेक्ट किया हुआ है.\n\nयदि आप ओवर द एयर एंटेना का उपयोग कर रहे हैं, तो उसकी स्थिति या दिशा समायोजित करें. अच्छे परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास लगाएं और दोबारा स्कैन करें."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"स्कैन में कोई चैनल नहीं मिला. सत्यापित करें कि नेटवर्क ट्यूनर चालू है और किसी टीवी संकेत स्रोत से कनेक्ट है.\n\nयदि किसी ओवर-द-एयर एंटेना का उपयोग कर रहे हैं, तो उसका स्थान या दिशा समायोजित करें. सर्वश्रेष्ठ परिणामों के लिए, उसे ऊंचाई पर और किसी खिड़की के पास रखें और फिर से स्कैन करें."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"दोबारा स्‍कैन करें"</item>
     <item msgid="2092797862490235174">"हो गया"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"टीवी चैनलों के लिए स्‍कैन करें"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"टीवी ट्यूनर सेटअप"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB टीवी ट्यूनर सेटअप"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB टीवी ट्यूनर डिस्कनेक्ट किया गया."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"टीवी चैनलों के लिए स्‍कैन करें"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"टीवी ट्यूनर सेटअप"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB टीवी ट्यूनर सेटअप"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"नेटवर्क टीवी ट्यूनर सेटअप"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB टीवी ट्यूनर डिसकनेक्ट किया गया."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"नेटवर्क ट्यूनर डिसकनेक्ट किया गया."</string>
 </resources>
diff --git a/usbtuner-res/values-hr/strings.xml b/usbtuner-res/values-hr/strings.xml
index 4a00dea..42f5c3a 100644
--- a/usbtuner-res/values-hr/strings.xml
+++ b/usbtuner-res/values-hr/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV prijemnik"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV prijemnik"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Uključeno"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Isključeno"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Mrežni TV prijemnik (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Pričekajte da obrada završi"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Odaberite izvor kanala"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Nema signala"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Namještanje na kanal <xliff:g id="CHANNEL_NAME">%s</xliff:g> nije uspjelo"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Namještanje nije uspjelo"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Softver prijemnika nedavno je ažuriran. Ponovite traženje kanala."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Omogućite okružujući zvuk u postavkama zvuka na razini sustava da biste omogućili audio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Zvuk se ne može reproducirati. Pokušajte s drugim televizorom"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Postavljanje prijemnika kanala"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Postavljanje TV prijemnika"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Postavljanje USB prijemnika za kanale"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Postavljanje mrežnog prijemnika"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Provjerite je li televizor povezan s izvorom televizijskog signala.\n\nAko upotrebljavate antenu zemaljske televizije, možda ćete joj morati promijeniti položaj ili smjer da biste pronašli najviše kanala. Za najbolje rezultate postavite je visoko i u blizini prozora."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Provjerite je li USB prijemnik priključen i povezan s izvorom TV signala.\n\nAko upotrebljavate antenu zemaljske televizije, možda trebate prilagoditi njezin položaj ili smjer da biste primali najviše kanala. Za najbolje rezultate postavite je visoko i u blizini prozora."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Provjerite je li mrežni prijemnik uključen i povezan s izvorom TV signala.\n\nAko upotrebljavate bežičnu antenu, možda ćete trebati prilagoditi položaj ili smjer da biste pronašli najviše kanala. Za najbolje rezultate postavite je visoko i blizu prozora."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Nastavi"</item>
     <item msgid="727245208787621142">"Ne sada"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Želite li ponovo pokrenuti postavljanje kanala?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Time će se ukloniti kanali pronađeni pomoću TV prijemnika i ponovo pokrenuti pretraživanje kanala.\n\nProvjerite je li televizor povezan s izvorom televizijskog signala.\n\nAko upotrebljavate antenu zemaljske televizije, možda ćete joj morati promijeniti položaj ili smjer da biste pronašli najviše kanala. Za najbolje rezultate postavite je visoko i u blizini prozora."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Time će se ukloniti kanali pronađeni putem USB prijemnika i ponoviti pretraživanje kanala.\n\nProvjerite je li USB prijemnik priključen i povezan s izvorom televizijskog signala.\n\nAko upotrebljavate antenu zemaljske televizije, možda trebate prilagoditi njezin položaj ili smjer da biste primali najviše kanala. Za najbolje rezultate postavite je visoko i u blizini prozora."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Time će se ukloniti kanali pronađeni mrežnim prijemnikom i pokrenuti pretraživanje novih kanala.\n\nProvjerite je li mrežni prijemnik uključen i povezan s izvorom TV signala.\n\nAko upotrebljavate bežičnu antenu, možda ćete trebati prilagoditi položaj ili smjer da biste pronašli najviše kanala. Za najbolje rezultate postavite je visoko i blizu prozora."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Nastavi"</item>
     <item msgid="235450158666155406">"Odustani"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Postavljanje TV prijemnika"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Postavljanje USB prijemnika za kanale"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Postavljanje prijemnika za mrežne kanale"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"To može potrajati nekoliko minuta"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Prijemnik trenutačno nije dostupan ili se već upotrebljava za snimanje."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -79,12 +79,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nije pronađen nijedan kanal"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Tijekom pretraživanja nije pronađen nijedan kanal. Provjerite je li televizor povezan s izvorom televizijskog signala.\n\nAko upotrebljavate antenu zemaljske televizije, promijenite joj položaj ili smjer. Za najbolje rezultate postavite je visoko i u blizini prozora, a zatim pretražite ponovo."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Pretraživanjem nije pronađen nijedan kanal. Provjerite je li USB prijemnik priključen i povezan s izvorom televizijskog signala.\n\nAko upotrebljavate antenu zemaljske televizije, prilagodite joj položaj ili smjer. Za najbolje rezultate postavite je visoko i u blizini prozora i pretražite ponovo."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Nije pronađen nijedan kanal. Provjerite je li mrežni prijemnik uključen i povezan s izvorom TV signala.\n\nAko upotrebljavate bežičnu antenu, prilagodite položaj ili smjer. Za najbolje rezultate postavite je visoko i blizu prozora i pretražite ponovo."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Pretraži ponovo"</item>
     <item msgid="2092797862490235174">"Gotovo"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Pretražite TV kanale"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Postavljanje TV prijemnika"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Postavljanje USB TV prijemnika"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV prijemnik isključen."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Pretražite TV kanale"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Postavljanje TV prijemnika"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Postavljanje USB TV prijemnika"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Postavljanje mrežnog TV prijemnika"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV prijemnik isključen."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Mrežni prijemnik isključen."</string>
 </resources>
diff --git a/usbtuner-res/values-hu/strings.xml b/usbtuner-res/values-hu/strings.xml
index e2bca51..0d83fe3 100644
--- a/usbtuner-res/values-hu/strings.xml
+++ b/usbtuner-res/values-hu/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Tévétuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-s tévétuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Be"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Ki"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Hálózati tévétuner (BÉTA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Kérjük, várja meg a folyamat befejezését"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Válassza ki a csatornaforrást"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Nincs jel"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Nem sikerült behangolni a(z) <xliff:g id="CHANNEL_NAME">%s</xliff:g> csatornát"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Nem sikerült a hangolás"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"A tuner szoftverét nemrég frissítették. Kérjük, ismételje meg a csatornakeresést."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"A hang aktiválásához engedélyezze a térhatású hangot a rendszerszintű hangbeállításokban"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"A hangot nem lehet lejátszani. Kérjük, próbálkozzon másik tévén"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Csatornatuner beállítása"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Tévétuner beállítása"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB-s csatornatuner beállítása"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Hálózati tuner beállítása"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Ellenőrizze, hogy tévéje csatlakoztatva van-e a televíziós jelforráshoz.\n\nAntenna használata esetén szükség lehet az elhelyezés, illetve az irány módosítására a lehető legtöbb csatorna befogásához. A legjobb eredmény érdekében helyezze magasra és ablak közelébe."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Győződjön meg arról, hogy az USB-tuner be van dugva, és csatlakoztatva van a televíziós jelforráshoz.\n\nAntenna használata esetén szükség lehet az elhelyezés, illetve irány módosítására a lehető legtöbb csatorna befogásához. A legjobb eredmény érdekében helyezze magasra és ablak közelébe."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Ellenőrizze, hogy a hálózati tuner be van-e kapcsolva, és csatlakozik-e televíziós jelforráshoz.\n\nHa antennát használ, módosítsa az elhelyezkedését, illetve irányát, hogy minél több csatornát fogjon. A legjobb eredmény érdekében helyezze magasra és ablak közelébe."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Folytatás"</item>
     <item msgid="727245208787621142">"Most nem"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Újra végrehajtja a csatornabeállítást?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Ezzel eltávolítja a tévétuner segítségével megtalált csatornákat, és új csatornakeresést indít.\n\nEllenőrizze, hogy tévéje csatlakoztatva van-e a televíziós jelforráshoz.\n\nAntenna használata esetén szükség lehet az elhelyezés, illetve az irány módosítására a lehető legtöbb csatorna befogásához. A legjobb eredmény érdekében helyezze magasra és ablak közelébe."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Ezzel eltávolítja a már megtalált csatornákat az USB-tunerről, és újból elvégzi a csatornakeresést.\n\nGyőződjön meg arról, hogy az USB-tuner be van dugva, és csatlakoztatva van a televíziós jelforráshoz.\n\nAntenna használata esetén szükség lehet az elhelyezés, illetve irány módosítására a lehető legtöbb csatorna befogásához. A legjobb eredmény érdekében helyezze magasra és ablak közelébe."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Ezzel eltávolítja a hálózati tuner által talált csatornákat, és újabb csatornakeresést indít el.\n\nEllenőrizze, hogy a hálózati tuner be van-e kapcsolva, és csatlakozik-e televíziós jelforráshoz.\n\nHa antennát használ, módosítsa az elhelyezkedését, illetve irányát, hogy minél több csatornát fogjon. A legjobb eredmény érdekében helyezze magasra és ablak közelébe."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Folytatás"</item>
     <item msgid="235450158666155406">"Mégse"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Tévétuner beállítása"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB-s csatornatuner beállítása"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Hálózati csatornatuner beállítása"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Ez néhány percet is igénybe vehet"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"A tuner átmenetileg nem áll rendelkezésre, vagy már fel lett használva a felvétel során."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nem található csatorna"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"A keresés nem talált csatornát. Ellenőrizze, hogy tévéje csatlakoztatva van-e a televíziós jelforráshoz.\n\nAntenna használata esetén módosítsa annak elhelyezését, illetve irányát. A legjobb eredmény érdekében helyezze magasra és ablak közelébe, majd ismételje meg a keresést."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"A keresés nem talált csatornát. Győződjön meg arról, hogy az USB-tuner be van dugva, és csatlakoztatva van a televíziós jelforráshoz.\n\nHa antennát használ, állítson annak helyzetén, illetve irányán. A legjobb eredmény érdekében helyezze magasra és ablak közelébe, majd ismételje meg a keresést."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"A rendszer nem talált egyetlen csatornát sem. Ellenőrizze, hogy a hálózati tuner be van-e kapcsolva, és csatlakozik-e televíziós jelforráshoz.\n\nHa antennát használ, módosítsa az elhelyezkedését, illetve irányát. A legjobb eredmény érdekében helyezze magasra és ablak közelébe, majd ismételje meg a keresést."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Keresés újra"</item>
     <item msgid="2092797862490235174">"Kész"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Tévécsatornák keresése"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Tévétuner beállítása"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB-s tévétuner beállítása"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Megszakadt a kapcsolat az USB-s tévétunerrel."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Tévécsatornák keresése"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Tévétuner beállítása"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB-s tévétuner beállítása"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Hálózati tévétuner beállítása"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Megszakadt a kapcsolat az USB-s tévétunerrel."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Megszakadt a kapcsolat a hálózati tunerrel."</string>
 </resources>
diff --git a/usbtuner-res/values-hy/strings.xml b/usbtuner-res/values-hy-rAM/strings.xml
similarity index 73%
rename from usbtuner-res/values-hy/strings.xml
rename to usbtuner-res/values-hy-rAM/strings.xml
index a8e33ea..2d3080c 100644
--- a/usbtuner-res/values-hy/strings.xml
+++ b/usbtuner-res/values-hy-rAM/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Հեռուստակարգավորիչ"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB հեռուստակարգավորիչ"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Միացնել"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Անջատել"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Ցանցային հեռուստաընդունիչ (ԲԵՏԱ)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Սպասեք՝ մինչ որոնումը ավարտվի"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Ընտրեք ալիքի աղբյուրը"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Ազդանշան չկա"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Չհաջողվեց անցնել <xliff:g id="CHANNEL_NAME">%s</xliff:g> ալիքին"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Չհաջողվեց անցնել ալիքին"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Ընդունիչի ծրագրակազմը վերջերս թարմացվել է: Նորից որոնեք ալիքները:"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Ձայնը միացնելու համար համակարգի ձայնի կարգավորումներում ակտիվացրեք ծավալային ձայնը"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Հնարավոր չէ վերարտադրել ձայնը: Փորձեք մեկ այլ հեռուստացույց:"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Ալիքների կարգավորիչի տեղադրում"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Հեռուստակարգավորիչի տեղադրում"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Ալիքների USB կարգավորիչի տեղադրում"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Ցանցային ընդունիչի կարգավորում"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Համոզվեք, որ հեռուստացույցը միացված է հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս հնարավոր է՝ անհրաժեշտ լինի կարգավորել դրա դիրքն ու ուղղությունը՝ ավելի շատ ալիքներ գտնելու համար: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ:"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Համոզվեք, որ USB կարգավորիչը միացված է ցանցին և հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս հնարավոր է՝ անհրաժեշտ լինի կարգավորել դրա դիրքն ու ուղղությունը՝ ավելի շատ ալիքներ գտնելու համար: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ:"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Համոզվեք, որ ցանցային ընդունիրչը միացված է և կապակցված հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս հնարավոր է՝ անհրաժեշտ լինի կարգավորել դրա դիրքն ու ուղղությունը՝ ավելի շատ ալիքներ գտնելու համար: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ:"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Շարունակել"</item>
     <item msgid="727245208787621142">"Ոչ հիմա"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Կրկի՞ն կարգավորել ալիքները:"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Այս գործողության արդյունքում կհեռացվեն հեռուստակարգավորիչից ստացված ալիքները և կկատարվի ալիքների նոր որոնում:\n\nՀամոզվեք, որ հեռուստացույցը միացված է հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս հնարավոր է՝ անհրաժեշտ լինի կարգավորել դրա դիրքն ու ուղղությունը՝ ավելի շատ ալիքներ գտնելու համար: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ:"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Այս գործողության արդյունքում կհեռացվեն USB կարգավորիչից ստացված ալիքները և կկատարվի ալիքների նոր որոնում:\n\nՀամոզվեք, որ USB կարգավորիչը միացված է ցանցին և հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս հնարավոր է՝ անհրաժեշտ լինի կարգավորել դրա դիրքն ու ուղղությունը՝ ավելի շատ ալիքներ գտնելու համար: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ:"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Այս գործողության արդյունքում կհեռացվեն ցանցային ընդունիչից ստացված ալիքները և կկատարվի ալիքների նոր որոնում:\n\nՀամոզվեք, որ ցանցային ընդունիչը միացված է և կապակցված հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս հնարավոր է՝ անհրաժեշտ լինի կարգավորել դրա դիրքն ու ուղղությունը՝ ավելի շատ ալիքներ գտնելու համար: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ:"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Շարունակել"</item>
     <item msgid="235450158666155406">"Չեղարկել"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Հեռուստակարգավորիչի տեղադրում"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Ալիքների USB կարգավորիչի տեղադրում"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Ցանցային ալիքների ընդունիչի տեղադրում"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Դա կարող է տևել մի քանի րոպե"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Ընդունիչը ժամանակավորապես անհասանելի է կամ արդեն օգտագործվում է տեսագրելու համար:"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Ալիքներ չեն գտնվել"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Որոնման արդյունքում ալիքներ չեն գտնվել: Համոզվեք, որ հեռուստացույցը միացված է հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս կարգավորեք դրա դիրքն ու ուղղությունը: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ, ապա որոնեք նորից:"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Որոնման արդյունքում ալիքներ չեն գտնվել: Համոզվեք, որ USB կարգավորիչը միացված է ցանցին և հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս կարգավորեք դրա դիրքն ու ուղղությունը: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ, ապա որոնեք նորից:"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Որոնման արդյունքում ալիքներ չեն գտնվել: Համոզվեք, որ ցանցային ընդունիչը միացված է և կապակցված հեռուստատեսային ազդանշանի աղբյուրին:\n\nԵթերային ալեհավաք օգտագործելիս կարգավորեք դրա դիրքն ու ուղղությունը: Լավագույն արդյունքներն ապահովելու համար այն դրեք բարձր տեղում՝ պատուհանի մոտ, ապա որոնեք նորից:"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Կրկին որոնել"</item>
     <item msgid="2092797862490235174">"Պատրաստ է"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Հեռուստաալիքների որոնում"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Հեռուստակարգավորիչի տեղադրում"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB հեռուստակարգավորիչի տեղադրում"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB հեռուստակարգավորիչն անջատված է:"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TV ալիքների որոնում"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV ընդունիչի տեղադրում"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV ընդունիչի տեղադրում"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Ցանցային TV ընդունիչի տեղադրում"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB հեռուստաընդունիչն անջատված է:"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Ցանցային ընդունիչն անջատված է։"</string>
 </resources>
diff --git a/usbtuner-res/values-in/strings.xml b/usbtuner-res/values-in/strings.xml
index e534c9c..8f3aa4d 100644
--- a/usbtuner-res/values-in/strings.xml
+++ b/usbtuner-res/values-in/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Tuner TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Tuner TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Aktif"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Nonaktif"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Tuner TV Jaringan (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Harap tunggu sampai pemrosesan selesai"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Pilih sumber saluran Anda"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Tidak Ada Sinyal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Gagal menyetel ke <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Gagal menyetel"</string>
-    <string name="ut_rescan_needed" msgid="2273655435759849436">"Perangkat lunak tuner ini baru saja diperbarui. Pindai ulang saluran Anda."</string>
+    <string name="ut_rescan_needed" msgid="2273655435759849436">"Software tuner ini baru saja diperbarui. Pindai ulang saluran Anda."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Aktifkan suara surround di setelan suara sistem untuk mengaktifkan audio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Tidak dapat memutar audio. Coba TV lainnya"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Penyiapan penyetel saluran"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Penyiapan Tuner TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Penyiapan tuner saluran USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Penyiapan tuner jaringan"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Pastikan TV terhubung ke sumber sinyal TV.\n\nJika menggunakan antena udara, Anda mungkin perlu menyesuaikan tempat atau arahnya untuk menerima sebagian besar saluran. Untuk hasil terbaik, tempatkan di lokasi yang tinggi dan dekat dengan jendela."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Pastikan tuner USB dicolokkan dan tersambung ke sumber sinyal TV.\n\nJika menggunakan antena udara, Anda mungkin perlu menyesuaikan tempat atau arahnya untuk menerima jumlah saluran paling banyak. Untuk hasil terbaik, letakkan di tempat yang tinggi dan dekat jendela."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Pastikan tuner jaringan aktif dan terhubung ke sumber sinyal TV.\n\nJika menggunakan antena udara, Anda mungkin perlu menyesuaikan tempat dan arahnya agar dapat menerima sebagian besar saluran. Untuk hasil terbaik, tempatkan antena di lokasi yang tinggi dan dekat jendela."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Lanjutkan"</item>
     <item msgid="727245208787621142">"Jangan sekarang"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Jalankan lagi penyiapan saluran?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Tindakan ini akan menghapus saluran yang ditemukan dari tuner TV dan memindai saluran baru lagi.\n\nPastikan TV terhubung ke sumber sinyal TV.\n\nJika menggunakan antena udara, mungkin Anda perlu menyesuaikan tempat atau arahnya untuk menerima sebagian besar saluran. Untuk hasil terbaik, tempatkan di lokasi yang tinggi dan dekat dengan jendela."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Tindakan ini akan menghapus saluran yang ditemukan dari tuner USB dan memindai saluran baru lagi.\n\nPastikan tuner USB dicolokkan dan tersambung ke sumber sinyal TV.\n\nJika menggunakan antena udara, Anda mungkin perlu menyesuaikan tempat atau arahnya untuk menerima jumlah saluran paling banyak. Untuk hasil terbaik, letakkan di tempat yang tinggi dan dekat jendela."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Hal ini akan menghapus saluran yang ditemukan dari tuner jaringan dan memindai saluran baru lagi.\n\nPastikan tuner jaringan aktif dan terhubung ke sumber sinyal TV.\n\nJika menggunakan antena udara, Anda mungkin perlu menyesuaikan penempatan atau arahnya agar dapat menerima sebagian besar saluran. Untuk hasil terbaik, tempatkan antena di lokasi yang tinggi dan dekat dengan jendela."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Lanjutkan"</item>
     <item msgid="235450158666155406">"Batal"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Penyiapan tuner TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Penyiapan tuner saluran USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Penyiapan tuner saluran jaringan"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Proses ini dapat memakan waktu beberapa menit"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuner sementara tidak tersedia atau sudah digunakan oleh rekaman."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Tidak ditemukan Saluran"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Pemindaian tidak menemukan saluran apa pun. Pastikan TV terhubung ke sumber sinyal TV.\n\nJika menggunakan antena udara, sesuaikan tempat atau arahnya. Untuk hasil terbaik, tempatkan di lokasi yang tinggi dan dekat dengan jendela kemudian pindai lagi."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Pemindaian tidak menemukan saluran apa pun. Pastikan tuner USB dicolokkan dan tersambung ke sumber sinyal TV.\n\nJika menggunakan antena udara, sesuaikan tempat atau arahnya. Untuk hasil terbaik, letakkan di tempat yang tinggi dan dekat jendela lalu pindai lagi."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Tidak menemukan saluran apa pun saat memindai. Pastikan tuner jaringan aktif dan terhubung ke sumber sinyal TV.\n\nJika Anda menggunakan antena udara, sesuaikan penempatan atau arahnya. Untuk hasil terbaik, tempatkan di lokasi yang tinggi dan dekat jendela, lalu pindai lagi."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Pindai lagi"</item>
     <item msgid="2092797862490235174">"Selesai"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Pindai saluran TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Penyiapan Tuner TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Penyiapan Tuner TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Koneksi tuner TV USB terputus."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Pindai saluran TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Penyiapan Tuner TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Penyiapan Tuner TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Penyiapan Tuner TV Jaringan"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Koneksi tuner TV USB terputus."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Koneksi tuner jaringan terputus."</string>
 </resources>
diff --git a/usbtuner-res/values-is/strings.xml b/usbtuner-res/values-is-rIS/strings.xml
similarity index 74%
rename from usbtuner-res/values-is/strings.xml
rename to usbtuner-res/values-is-rIS/strings.xml
index f63d981..fa1e85c 100644
--- a/usbtuner-res/values-is/strings.xml
+++ b/usbtuner-res/values-is-rIS/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sjónvarpsmóttakari"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-sjónvarpsmóttakari"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Kveikja"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Slökkva"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Netsjónvarpsmóttakari (TILRAUNAÚTGÁFA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Bíddu þar til vinnslu lýkur"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Veldu inntak rása"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Ekkert merki"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Mistókst að stilla á <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Mistókst að stilla"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Hugbúnaður sjónvarpsmóttakarans var uppfærður nýlega. Leitaðu aftur að rásum."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Kveikja á víðómastillingu í hljóðstillingum kerfisins til að kveikja á hljóði"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Ekki er hægt að spila hljóð. Prófaðu annað sjónvarp"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Uppsetning sjónvarpskorts"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Uppsetning sjónvarpsmóttakara"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Uppsetning USB-sjónvarpsrásakorts"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Uppsetning netsjónvarpsmóttakara"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Gakktu úr skugga um að sjónvarpið sé tengt við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt. Best er að hafa það hátt uppi og nálægt glugga þegar leitað er."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Gakktu úr skugga um að USB-sjónvarpskortið sé í sambandi og tengt við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt til að ná fleiri rásum. Best er að hafa það hátt uppi og nálægt glugga."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Gakktu úr skugga um að kveikt sé á netsjónvarpsmóttakaranum og að hann sé tengdur við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt. Best er að hafa það hátt uppi og nálægt glugga þegar leitað er."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Halda áfram"</item>
     <item msgid="727245208787621142">"Ekki núna"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Viltu keyra rásauppsetningu aftur?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Þetta fjarlægir stöðvar sem sjónvarpsmóttakarinn fann og leitar aftur að nýjum stöðvum.\n\nGakktu úr skugga um að sjónvarpið sé tengt við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt. Best er að hafa það hátt uppi og nálægt glugga þegar leitað er."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Þetta fjarlægir rásir sem skráðar eru á USB-sjónvarpskortinu og leitar að nýjum stöðvum.\n\nGakktu úr skugga um að USB-sjónvarpskortið sé í sambandi og tengt við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt til að ná fleiri rásum. Best er að hafa það hátt uppi og nálægt glugga."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Þetta fjarlægir rásirnar sem sjónvarpsmóttakarinn þinn fann og leitar aftur að nýjum rásum.\n\nGakktu úr skugga um að kveikt sé á netsjónvarpsmóttakaranum og að hann sé tengdur við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt. Best er að hafa það hátt uppi og nálægt glugga þegar leitað er."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Halda áfram"</item>
     <item msgid="235450158666155406">"Hætta við"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Uppsetning sjónvarpsmóttakara"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Uppsetning USB-sjónvarpsrásakorts"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Uppsetning netsjónvarpsmóttakara"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Þetta getur tekið nokkrar mínútur"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Móttakari er tímabundið ekki í boði eða er þegar að taka upp."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Engar rásir fundust"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Engar rásir fundust. Gakktu úr skugga um að sjónvarpið sé tengt við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt. Best er að hafa það hátt uppi og nálægt glugga þegar leitað er."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Engar rásir fundust. Gakktu úr skugga um að USB-sjónvarpskortið sé í sambandi og tengt við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt. Best er að hafa það hátt uppi og nálægt glugga þegar leitað er."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Leitin fann engar stöðvar. Gakktu úr skugga um að kveikt sé á netsjónvarpsmóttakaranum og hann sé tengdur við sjónvarpstengi.\n\nEf þú ert að nota loftnet skaltu færa það á annan stað eða snúa því í aðra átt. Best er að hafa það hátt uppi og nálægt glugga þegar leitað er."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Leita aftur"</item>
     <item msgid="2092797862490235174">"Lokið"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Skanna eftir sjónvarpsstöðvum"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Uppsetning sjónvarpsmóttakara"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Uppsetning USB-sjónvarpsmóttakara"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-sjónvarpsmóttakari tekinn úr sambandi."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Skanna eftir sjónvarpsstöðvum"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Uppsetning sjónvarpsmóttakara"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Uppsetning USB-sjónvarpsmóttakara"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Uppsetning netsjónvarpsmóttakara"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-sjónvarpsmóttakari tekinn úr sambandi."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Netmóttakari tekinn úr sambandi."</string>
 </resources>
diff --git a/usbtuner-res/values-it/strings.xml b/usbtuner-res/values-it/strings.xml
index 7787d01..3e15fb2 100644
--- a/usbtuner-res/values-it/strings.xml
+++ b/usbtuner-res/values-it/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sintonizzatore TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Sintonizzatore TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Attiva"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Disattiva"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Attendi il completamento dell\'elaborazione"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Seleziona la tua fonte canale"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Nessun segnale"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Sintonizzazione su <xliff:g id="CHANNEL_NAME">%s</xliff:g> non riuscita"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Sintonizzazione non riuscita"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Il software del sintonizzatore è stato aggiornato di recente. Esegui nuovamente la scansione dei canali."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Per attivare l\'audio, attiva l\'audio surround nelle impostazioni del sistema"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Impossibile riprodurre l\'audio. Prova con un\'altra TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configurazione del sintonizzatore di canali"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configurazione del sintonizzatore TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configurazione del sintonizzatore di canali USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configurazione del sintonizzatore di rete"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Verifica che la TV sia connessa a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA, regolane la posizione o la direzione per ricevere la maggior parte dei canali. Per ottenere risultati ottimali, posizionala in alto e vicino a una finestra."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Verifica che il sintonizzatore USB sia collegato e connesso a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA, potresti dover regolare la sua posizione o direzione per ricevere la maggior parte dei canali. Per risultati ottimali, posizionala in alto e vicino a una finestra."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Verifica che il sintonizzatore di rete sia acceso e connesso a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA (over-the-air), potresti doverne regolare la posizione o la direzione per ricevere il maggior numero di canali. Per ottenere risultati ottimali, posizionala in alto, vicino a una finestra."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continua"</item>
     <item msgid="727245208787621142">"Non ora"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Eseguire nuovamente la configurazione dei canali?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Questa operazione rimuoverà i canali trovati dal sintonizzatore TV ed eseguirà la ricerca di nuovi canali.\n\nVerifica che la TV sia connessa a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA, regolane la posizione o la direzione per ricevere la maggior parte dei canali. Per ottenere risultati ottimali, posizionala in alto e vicino a una finestra."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Questa operazione rimuoverà i canali trovati dal sintonizzatore USB ed eseguirà la ricerca di nuovi canali.\n\nVerifica che il sintonizzatore USB sia collegato e connesso a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA, potresti dover regolare la sua posizione o direzione per ricevere il maggior numero di canali. Per ottenere risultati ottimali, posizionala in alto e vicino a una finestra."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"I canali trovati dal sintonizzatore di rete verranno rimossi e verrà eseguita nuovamente la ricerca di nuovi canali.\n\nVerifica che il sintonizzatore di rete sia acceso e connesso a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA (over-the-air), potresti doverne regolare la posizione o la direzione per ricevere il maggior numero di canali. Per ottenere risultati ottimali, posizionala in alto, vicino a una finestra."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continua"</item>
     <item msgid="235450158666155406">"Annulla"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configurazione del sintonizzatore TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configurazione del sintonizzatore di canali USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configurazione del sintonizzatore di canali della rete"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"L\'operazione potrebbe richiedere alcuni minuti"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Il sintonizzatore è temporaneamente non disponibile o già utilizzato dal registratore."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nessun canale trovato"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Nessun canale trovato durante la ricerca. Verifica che la TV sia connessa a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA, regolane la posizione o la direzione. Per ottenere risultati ottimali, posizionala in alto, vicino a una finestra ed esegui nuovamente la ricerca."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Nessun canale trovato durante la ricerca. Verifica che il sintonizzatore USB sia collegato e connesso a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA (over-the-air), regolane la posizione o la direzione. Per ottenere risultati ottimali, posizionala in alto, vicino a una finestra ed esegui nuovamente la ricerca."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Nessun canale trovato durante la ricerca. Verifica che il sintonizzatore di rete sia acceso e connesso a un\'origine del segnale TV.\n\nSe utilizzi un\'antenna OTA (over-the-air), regolane la posizione o la direzione. Per ottenere risultati ottimali, posizionala in alto, vicino a una finestra ed esegui nuovamente la ricerca."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Cerca di nuovo"</item>
     <item msgid="2092797862490235174">"Fine"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Cerca canali TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configurazione del sintonizzatore TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configurazione del sintonizzatore TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Sintonizzatore TV USB disconnesso."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Cerca canali TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configurazione del sintonizzatore TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configurazione del sintonizzatore TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configurazione del sintonizzatore TV di rete"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Sintonizzatore TV USB disconnesso."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Sintonizzatore di rete disconnesso."</string>
 </resources>
diff --git a/usbtuner-res/values-iw/strings.xml b/usbtuner-res/values-iw/strings.xml
index 5dab5f1..d30fdac 100644
--- a/usbtuner-res/values-iw/strings.xml
+++ b/usbtuner-res/values-iw/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"טיונר טלוויזיה"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"‏טיונר ה-USB בטלוויזיה"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"מופעל"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"כבוי"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"טיונר טלוויזיה לרשת (ביטא)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"המתן לסיום העיבוד"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"בחר את מקור הערוצים"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"אין אות"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"לא ניתן היה לכוון לערוץ <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"הכוונון נכשל"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"תוכנת הטיונר עודכנה לאחרונה. סרוק מחדש את הערוצים."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"הפעל סראונד בהגדרות צלילי מערכת כדי להפעיל אודיו"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"אין אפשרות להשמיע אודיו. נסה ערוץ טלוויזיה אחר."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"הגדרת טיונר ערוצים"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"הגדרת טיונר טלוויזיה"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"‏הגדרת טיונר ערוצים בחיבור USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"הגדרת מקלט הרשת"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"ודא שהטלוויזיה מחוברת למקור אות טלוויזיה.\n\nאם אתה משתמש באנטנה אלחוטית, ייתכן שיהיה עליך לשנות את המיקום או את הכיוון שלה כדי לקלוט כמה שיותר ערוצים. לקבלת התוצאות הטובות ביותר, הצב אותה במקום גבוה ליד חלון."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"‏ודא שטיונר USB מחובר למקור אות בטלוויזיה. \n\n אם אתה משתמש באנטנה אלחוטית, ייתכן שיהיה עליך לכוון את מיקומה או את כיוונה כדי לקלוט כמה שיותר ערוצים. לתוצאות מיטביות, הצב אותה במקום גבוה ליד חלון וסרוק שוב."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"ודא שמקלט הרשת מופעל ומחובר למקור אות של טלוויזיה.\n\nאם אתה משתמש באנטנה לקליטת שידורים אלחוטיים, ייתכן שיהיה עליך לשנות את המיקום או את הכיוון שלה כדי לקלוט כמה שיותר ערוצים. לקבלת התוצאות הטובות ביותר, הצב אותה במקום גבוה ליד חלון."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"המשך"</item>
     <item msgid="727245208787621142">"לא עכשיו"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"האם להפעיל מחדש את הגדרת הערוצים?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"פעולה זו תסיר את הערוצים שנמצאו בטיונר הטלוויזיה ותסרוק שוב ערוצים חדשים.\n\nודא שהטלוויזיה מחוברת למקור אות טלוויזיה.\n\nאם אתה משתמש באנטנה אלחוטית, ייתכן שיהיה עליך לשנות את המיקום או את הכיוון שלה כדי לקלוט כמה שיותר ערוצים. לקבלת התוצאות הטובות ביותר, הצב אותה במקום גבוה ליד חלון."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"‏פעולה זו תסיר את הערוצים שנמצאו מטיונר ה-USB ותתבצע סריקה נוספת לערוצים חדשים.\n\nודא שטיונר USB מחובר למקור אות בטלוויזיה.\n\nאם אתה משתמש באנטנה אלחוטית, ייתכן שיהיה עליך לשנות את מיקומה או את כיוונה כדי לקלוט כמה שיותר ערוצים. לתוצאות מיטביות, הצב אותה במקום גבוה ליד חלון וסרוק שוב."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"הפעולה תסיר את הערוצים שנמצאו ממקלט הרשת ותתבצע שוב סריקה לאיתור ערוצים חדשים.\n\nודא שמקלט הרשת מופעל ומחובר למקור אות של טלוויזיה.\n\nאם אתה משתמש באנטנה לקליטת שידורים אלחוטיים, ייתכן שיהיה עליך לשנות את המיקום או את הכיוון שלה כדי לקלוט כמה שיותר ערוצים. לקבלת התוצאות הטובות ביותר, הצב אותה במקום גבוה ליד חלון."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"המשך"</item>
     <item msgid="235450158666155406">"ביטול"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"הגדרת טיונר טלוויזיה"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"‏הגדרת טיונר ערוצים בחיבור USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"הגדרת מקלט ערוצים לרשת"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"פעולה זו עשויה להימשך מספר דקות"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"הטיונר אינו זמין באופן זמני או שהוא כבר נמצא בשימוש של הקלטה."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -82,12 +82,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"לא נמצאו ערוצים"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"בסריקה לא נמצאו ערוצים. ודא שהטלוויזיה מחוברת למקור אות טלוויזיה.\n\nאם אתה משתמש באנטנה אלחוטית, שנה את המיקום או את הכיוון שלה. לקבלת התוצאות הטובות ביותר, הצב אותה במקום גבוה ליד חלון וסרוק שוב."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"‏לא נמצאו ערוצים בסריקה. ודא שטיונר USB מחובר למקור אות בטלוויזיה. \n\n אם אתה משתמש באנטנה אלחוטית, שנה את מיקומה או את כיוונה. לתוצאות מיטביות, הצב אותה במקום גבוה ליד חלון וסרוק שוב."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"בסריקה לא נמצאו ערוצים. ודא שמקלט הרשת מופעל ומחובר למקור אות של טלוויזיה.\n\nאם אתה משתמש באנטנה לקליטת שידורים אלחוטיים, שנה את המיקום או את הכיוון שלה. לקבלת התוצאות הטובות ביותר, הצב אותה במקום גבוה ליד חלון וסרוק שוב."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"סרוק שוב"</item>
     <item msgid="2092797862490235174">"סיום"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"סריקה לאיתור ערוצי טלוויזיה"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"הגדרת טיונר טלוויזיה"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"‏הגדרת טיונר ה-USB בטלוויזיה"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"‏טיונר ה-USB שבטלוויזיה מנותק."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"סריקה לאיתור ערוצי טלוויזיה"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"הגדרה של טיונר טלוויזיה"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"‏הגדרה של טיונר USB בטלוויזיה"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"הגדרה של טיונר טלוויזיה לרשת"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"‏טיונר ה-USB שבטלוויזיה מנותק."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"טיונר הרשת מנותק."</string>
 </resources>
diff --git a/usbtuner-res/values-ja/strings.xml b/usbtuner-res/values-ja/strings.xml
index 88af255..53223b4 100644
--- a/usbtuner-res/values-ja/strings.xml
+++ b/usbtuner-res/values-ja/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"テレビ チューナー"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB テレビ チューナー"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"ON"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"OFF"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"ネットワーク テレビ チューナー(ベータ版)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"処理が完了するまでこのままお待ちください"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"チャンネル ソースを選択してください"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"信号がありません"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"「<xliff:g id="CHANNEL_NAME">%s</xliff:g>」に合わせることができませんでした"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"合わせることができませんでした"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"最近チューナー ソフトウェアが更新されています。チャンネルをもう一度スキャンしてください。"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"音声を有効にするには、システムのサウンド設定でサラウンド サウンドをオンにしてください"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"音声を再生できません。別のテレビをお試しください"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"チャンネル チューナーのセットアップ"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"テレビ チューナーのセットアップ"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB チャンネル チューナーのセットアップ"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"ネットワーク チューナーのセットアップ"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"テレビがテレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、チャンネルの多くを受信するためにアンテナの場所や方向の調節が必要になる場合があります。最良の結果を得るには、アンテナを窓際の高い位置に設置します。"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB チューナーが電源に接続され、テレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、チャンネルの多くを受信するためにアンテナの場所や方向の調節が必要になる場合があります。最良の結果を得るには、アンテナを窓際の高い位置に設置します。"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"ネットワーク チューナーの電源がオンになっていて、テレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、チャンネルの多くを受信するためにアンテナの場所や方向の調節が必要になる場合があります。最良の結果を得るには、アンテナを窓際の高い位置に設置します。"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"次へ"</item>
     <item msgid="727245208787621142">"後で"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"もう一度チャンネルを設定しますか?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"テレビ チューナーで見つかったチャンネルを削除して新しいチャンネルをもう一度スキャンします。\n\nテレビがテレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、チャンネルの多くを受信するためにアンテナの場所や方向の調節が必要になる場合があります。最良の結果を得るには、アンテナを窓際の高い位置に設置します。"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"USB チューナーで見つかったチャンネルを削除して新しいチャンネルをもう一度スキャンします。\n\nUSB チューナーが電源に接続され、テレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、チャンネルの多くを受信するためにアンテナの場所や方向の調節が必要になる場合があります。最良の結果を得るには、アンテナを窓際の高い位置に設置します。"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"ネットワーク チューナーで見つかったチャンネルを削除して新しいチャンネルをもう一度スキャンします。\n\nネットワーク チューナーの電源がオンになっていて、テレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、チャンネルの多くを受信するためにアンテナの場所や方向の調節が必要になる場合があります。最良の結果を得るには、アンテナを窓際の高い位置に設置します。"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"次へ"</item>
     <item msgid="235450158666155406">"キャンセル"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"テレビ チューナーのセットアップ"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB チャンネル チューナーのセットアップ"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"ネットワーク チャンネル チューナーのセットアップ"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"この処理には数分かかることがあります"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"チューナーを一時的に使用できないか、すでに録画に使用しています。"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"チャンネルが見つかりませんでした"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"スキャンの結果、チャンネルは見つかりませんでした。テレビがテレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、アンテナの場所や方向を調節してください。最良の結果を得るには、アンテナを窓際の高い位置に設置してから、もう一度スキャンします。"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"スキャンの結果、チャンネルは見つかりませんでした。USB チューナーが電源に接続され、テレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、アンテナの場所や方向を調節してください。最良の結果を得るには、アンテナを窓際の高い位置に設置してから、もう一度スキャンします。"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"スキャンの結果、チャンネルは見つかりませんでした。ネットワーク チューナーの電源がオンになっていて、テレビの信号源に接続されていることを確認してください。\n\n無線アンテナを使用している場合は、アンテナの場所や方向を調節してください。最良の結果を得るには、アンテナを窓際の高い位置に設置してから、もう一度スキャンします。"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"再スキャン"</item>
     <item msgid="2092797862490235174">"完了"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"テレビのチャンネルをスキャン"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"テレビ チューナーのセットアップ"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB テレビ チューナーのセットアップ"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV チューナーの接続が解除されています。"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"テレビのチャンネルをスキャン"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"テレビ チューナーのセットアップ"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB テレビ チューナーのセットアップ"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"ネットワーク テレビ チューナーのセットアップ"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB テレビ チューナーの接続が解除されています。"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"ネットワーク チューナーの接続が解除されています。"</string>
 </resources>
diff --git a/usbtuner-res/values-ka/strings.xml b/usbtuner-res/values-ka-rGE/strings.xml
similarity index 73%
rename from usbtuner-res/values-ka/strings.xml
rename to usbtuner-res/values-ka-rGE/strings.xml
index e09428d..055c4a9 100644
--- a/usbtuner-res/values-ka/strings.xml
+++ b/usbtuner-res/values-ka-rGE/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV-ტუნერი"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV-ტუნერი"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"ჩართვა"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"გამორთვა"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"ქსელის TV-ტუნერი (Beta)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"გთხოვთ, მოითმინოთ დამუშავების დასრულებამდე"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"აირჩიეთ არხების წყარო"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"სიგნალი არ არის"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g>-ზე გადართვა ვერ მოხერხდა"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"არხზე გადართვა ვერ მოხერხდა"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ტუნერის პროგრამული უზრუნველყოფა ახლახან განახლდა. გთხოვთ, ხელახლა დაასკანიროთ არხები."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"აუდიოს ჩასართავად, სისტემის ხმის პარამეტრებში ჩართეთ მოცულობითი ხმა"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"აუდიოს დაკვრა ვერ ხერხდება. გთხოვთ, ცადოთ სხვა არხი"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"არხების ტუნერის დაყენება"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV-ტუნერის დაყენება"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"არხების USB ტუნერის დაყენება"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"ქსელის ტუნერის დაყენება"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"დარწმუნდით, რომ თქვენი ტელევიზორი მიერთებულია სატელევიზიო სიგნალის წყაროსთან..\n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, არხების უმეტესობის მისაღებად, მისი განლაგების ან მიმართულების დარეგულება მოგიწევთ. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"დარწმუნდით, რომ USB ტუნერი ბუდეშია და მიერთებულია სატელევიზიო სიგნალის წყაროსთან.\n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, არხების უმეტესობის მისაღებად, მისი განლაგების ან მიმართულების დარეგულება მოგიწევთ. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"დარწმუნდით, რომ ქსელის ტუნერი ჩართულია და მიერთებულია სატელევიზიო სიგნალის წყაროსთან.\n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, არხების უმეტესობის მისაღებად, მისი განლაგების ან მიმართულების დარეგულირება მოგიწევთ. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"გაგრძელება"</item>
     <item msgid="727245208787621142">"ახლა არა"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"გსურთ არხების ხელახლა დაყენება?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"ეს მოქმედება ამოშლის TV ტუნერით ნაპოვნ არხებს და ახალი არხების სკანირება ხელახლა მოხდება.\n\nდარწმუნდით, რომ თქვენი ტელევიზორი მიერთებულია სატელევიზიო სიგნალის წყაროსთან.\n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, არხების უმეტესობის მისაღებად, მისი განლაგების ან მიმართულების დარეგულება მოგიწევთ. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"ეს მოქმედება ამოშლის USB ტუნერით ნაპოვნ არხებს და ხელახლა მოხდება ახალი არხების სკანირება.\n\nდარწმუნდით, რომ USB ტუნერი ბუდეშია და მიერთებულია სატელევიზიო სიგნალის წყაროსთან.\n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, არხების უმეტესობის მისაღებად, მისი განლაგების ან მიმართულების დარეგულება მოგიწევთ. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"ეს მოქმედება ამოშლის ქსელის ტუნერით ნაპოვნ არხებს და ახალი არხების სკანირება ხელახლა მოხდება.\n\nდარწმუნდით, რომ ქსელის ტუნერი ჩართულია და მიერთებულია სატელევიზიო სიგნალის წყაროსთან.\n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, არხების უმეტესობის მისაღებად, მისი განლაგების ან მიმართულების დარეგულირება მოგიწევთ. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"გაგრძელება"</item>
     <item msgid="235450158666155406">"გაუქმება"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV-ტუნერის დაყენება"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"არხების USB ტუნერის დაყენება"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"არხების ქსელის ტუნერის დაყენება"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"ამას შეიძლება რამდენიმე წუთი დასჭირდეს"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ტუნერი დროებით მიუწვდომელია, ან უკვე გამოიყენება ჩასაწერად."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"არხები ვერ მოიძებნა"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"სკანირებისას არხები ვერ მოიძებნა. დარწმუნდით, რომ თქვენი ტელევიზორი მიერთებულია სატელევიზიო სიგნალის წყაროსთან.\n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, დაარეგულირეთ მისი განლაგება ან მიმართულება. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს და ხელახლა დაასკანირეთ."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"სკანირებისას არხები ვერ მოიძებნა. დარწმუნდით, რომ USB ტუნერი ბუდეშია და მიერთებულია სატელევიზიო სიგნალის წყაროსთან. \n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, დაარეგულირეთ მისი განლაგება ან მიმართულება. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს და ხელახლა დაასკანირეთ."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"სკანირებისას არხები ვერ მოიძებნა. დარწმუნდით, რომ ქსელის ტუნერი ჩართულია და მიერთებულია სატელევიზიო სიგნალის წყაროსთან. \n\nტერესტრიული ანტენის გამოყენების შემთხვევაში, დაარეგულირეთ მისი განლაგება ან მიმართულება. საუკეთესო შედეგის მისაღებად, განათავსეთ ის სიმაღლეზე, ფანჯარასთან ახლოს და ხელახლა დაასკანირეთ."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"ხელახლა სკანირება"</item>
     <item msgid="2092797862490235174">"მზადაა"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"სატელევიზიო არხების სკანირება"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV-ტუნერის დაყენება"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV-ტუნერის დაყენება"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV-ტუნერი გაითიშა."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"სკანირება სატელევიზიო არხების აღმოსაჩენად"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV-ტუნერის დაყენება"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV-ტუნერის დაყენება"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"ქსელის TV-ტუნერის დაყენება"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV-ტუნერი გაითიშა."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"ქსელის ტუნერი გაითიშა."</string>
 </resources>
diff --git a/usbtuner-res/values-kk/strings.xml b/usbtuner-res/values-kk-rKZ/strings.xml
similarity index 72%
rename from usbtuner-res/values-kk/strings.xml
rename to usbtuner-res/values-kk-rKZ/strings.xml
index 3c2ba4f..7ca732b 100644
--- a/usbtuner-res/values-kk/strings.xml
+++ b/usbtuner-res/values-kk-rKZ/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ТД тюнері"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TД тюнері"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Қосу"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Өшіру"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Желілік теледидар тюнері (БЕТА НҰСҚАСЫ)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Өңдеу аяқталғанша күте тұрыңыз"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Арна көзін таңдаңыз"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Сигнал жоқ"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> арнасына реттелмеді"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Реттелмеді"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Тюнердің бағдарламалық құралы жақында жаңартылды. Арналарды қайта іздеңіз."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Аудиомазмұнды қосу үшін жүйенің параметрлерінде көлемдік дыбысты қосыңыз"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Аудиомазмұн ойнатылмайды. Басқа теледидар арнасын қосып көріңіз"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Арна тюнерін орнату"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"ТД тюнерін орнату"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB арна тюнерін орнату"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Желі тюнерін реттеу"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Теледидардың ТД сигнал көзіне қосылғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, көптеген арналарды қабылдау үшін оның орнын немесе бағытын реттеу қажет болады. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын орналастырыңыз."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB тюнерін жалғанғанын және ТД сигнал көзіне қосылғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, көптеген арналарды қабылдау үшін оның орнын немесе бағытын реттеу қажет болады. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын орналастырыңыз."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"USB тюнері қосылып, теледидардың сигнал көзіне жалғанғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, көптеген арналарды қабылдау үшін оның орнын ауыстырыңыз немесе бағытын реттеңіз. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын жерге орналастырыңыз."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Жалғастыру"</item>
     <item msgid="727245208787621142">"Қазір емес"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Арналарды қайта орнату қажет пе?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"ТД тюнерінде табылған арналар жойылып, жаңа арналар ізделеді.\n\nТеледидардың ТД сигнал көзіне қосылғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, көптеген арналарды қабылдау үшін оның орнын немесе бағытын реттеу қажет болады. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын орналастырыңыз."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"USB тюнерінде табылған арналар жойылып, жаңа арналар ізделеді.\n\nUSB тюнері жалғанғанын және ТД сигнал көзіне қосылғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, көптеген арналарды қабылдау үшін оның орнын немесе бағытын реттеу қажет болады. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын орналастырыңыз."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Желі тюнерінде табылған арналар өшіріліп, жаңа арналар ізделеді.\n\nЖелі тюнері қосылып, теледидардың сигнал көзіне жалғанғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, көптеген арналарды қабылдау үшін оның орнын ауыстырыңыз немесе бағытын реттеңіз. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын жерге орналастырыңыз."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Жалғастыру"</item>
     <item msgid="235450158666155406">"Бас тарту"</item>
@@ -54,8 +53,9 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"ТД тюнерін орнату"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB арна тюнерін орнату"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Желілік арна тюнерін реттеу"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Бұл бірнеше минутты алуы мүмкін"</string>
-    <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Тюнер қол жетімсіз немесе жазу барысында қолданылуда."</string>
+    <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Тюнер қолжетімсіз немесе жазу барысында қолданылуда."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
       <item quantity="other">%1$d арна табылды</item>
       <item quantity="one">%1$d арна табылды</item>
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Арналар табылмады"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Іздеу нәтижесінде ешқандай арна табылмады. Теледидардың ТД сигнал көзіне қосылғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, орнын немесе бағытын реттеңіз. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын орналастырып, қайта іздеп көріңіз."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Іздеу нәтижесінде арналар табылмады. USB тюнері жалғанғанын және ТД сигнал көзіне қосылғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, орнын немесе бағытын реттеңіз. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын орналастырып, қайта іздеп көріңіз."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Іздеу нәтижесінде арналар табылмады. Желі тюнері қосылып, теледидардың сигнал көзіне жалғанғанын тексеріңіз.\n\nСымсыз антеннаны пайдалансаңыз, оның орнын ауыстырыңыз немесе бағытын реттеңіз. Ең жақсы нәтижеге қол жеткізу үшін оны жоғарырақ және терезеге жақын жерге орналастырып, қайта іздеп көріңіз."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Қайта іздеу"</item>
     <item msgid="2092797862490235174">"Орындалды"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"ТД арналарын іздеу"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"ТД тюнерін орнату"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TД тюнерін орнату"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TД тюнері ажыратылды."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"ТД арналарын іздеу"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"ТД тюнерін орнату"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TД тюнерін орнату"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Желілік ТД тюнерін реттеу"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TД тюнері ажыратылды."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Желі тюнері ажыратылды."</string>
 </resources>
diff --git a/usbtuner-res/values-km/strings.xml b/usbtuner-res/values-km-rKH/strings.xml
similarity index 73%
rename from usbtuner-res/values-km/strings.xml
rename to usbtuner-res/values-km-rKH/strings.xml
index 904f3e5..5bca2a0 100644
--- a/usbtuner-res/values-km/strings.xml
+++ b/usbtuner-res/values-km-rKH/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"អង្គរាវប៉ុស្តិ៍ទូរទស្សន៍"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"ឧបករណ៍ USB រាវប៉ុស្តិ៍ទូរទស្សន៍"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"បើក"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"បិទ"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"កម្មវិធី​រាវ​បណ្តាញ​ទូរទស្សន៍ (បេតា)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"សូមរង់ចាំដើម្បីបញ្ចប់ដំណើរការ"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"ជ្រើសប្រភពប៉ុស្តិ៍របស់អ្នក"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"គ្មានរលកសញ្ញាទេ"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"បានបរាជ័យក្នុងការបើកប៉ុស្តិ៍ <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"បរាជ័យក្នុងការរាវប៉ុស្តិ៍"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"កម្មវិធីអង្គរាវប៉ុស្តិ៍បានអាប់ដេតថ្មីៗនេះ។ សូមស្កេនរកប៉ុស្តិ៍ទាំងនេះម្តងទៀត។"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"បើកដំណើរការសំឡេងជុំវិញនៅក្នុងការកំណត់សំឡេងប្រព័ន្ធដើម្បីបើកដំណើរការអូឌីយ៉ូ"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"មិនអាចចាក់អូឌីយ៉ូបានទេ។ សូមសាកល្បងប្រើទូរទស្សន៍ផ្សេង"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"ការដំឡើងអង្គរាវប៉ុស្តិ៍"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"ការដំឡើងអង្គរាវប៉ុស្តិ៍ទូរទស្សន៍"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"ការដំឡើងឧបករណ៍ USB រាវប៉ុស្តិ៍"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"រៀបចំឧបករណ៍រាវបណ្តាញ"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"សូមផ្ទៀងផ្ទាត់ថាប៉ុស្តិ៍ទូរទស្សន៍របស់អ្នកត្រូវបានភ្ជាប់ទៅប្រភពរលកសញ្ញាទូរទស្សន៍។\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ សូមសម្រួលទីតាំង ឬទិសដៅរបស់វាដើម្បីទទួលបានប៉ុស្តិ៍ច្រើនបំផុត។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងខ្ពស់ និងនៅជិតបង្អួច។"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"ផ្ទៀងផ្ទាត់ថាអ្នកបានដោតឧបករណ៍ USB រាវប៉ុស្តិ៍ និងបានភ្ជាប់ទៅប្រភពសញ្ញាទូរទស្សន៍\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ អ្នកប្រហែលជាត្រូវកែសម្រួលទីតាំង និងទិសដៅរបស់វាដើម្បីទទួលបានប៉ុស្តិ៍ច្រើនបំផុត។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងដែលខ្ពស់ក្បែរបង្អួច។"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"ផ្ទៀងផ្ទាត់ថាអ្នកបានបើកឧបករណ៍រាវបណ្តាញនេះ និងបានភ្ជាប់ទៅប្រភពរលកសញ្ញាទូរទស្សន៍។\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ អ្នកត្រូវកែសម្រួលទីតាំង និងទិសដៅរបស់វា ដើម្បីទទួលបានប៉ុស្តិ៍ច្រើនបំផុត។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងដែលខ្ពស់ក្បែរបង្អួច។"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"បន្ត"</item>
     <item msgid="727245208787621142">"មិនមែនឥឡូវនេះទេ"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"ដំណើរការដំឡើងប៉ុស្តិ៍ឡើងវិញឬទេ?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"វានឹងលុបប៉ុស្តិ៍ដែលបានរកឃើញដោយអង្គរាវប៉ុស្តិ៍ទូរទស្សន៍ចេញ ហើយស្កេនរកប៉ុស្តិ៍ថ្មីម្តងទៀត។\n\nផ្ទៀងផ្ទាត់ថាអ្នកបានដោតទូរទស្សន៍ទៅប្រភពរលកសញ្ញាទូរទស្សន៍\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ អ្នកប្រហែលជាត្រូវសម្រួលទីតាំង និងទិសដៅរបស់វាដើម្បីទទួលបានប៉ុស្តិ៍ច្រើនបំផុត។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងដែលខ្ពស់ក្បែរបង្អួច។"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"វានឹងលុបប៉ុស្តិ៍ដែលបានរកឃើញដោយឧបករណ៍ USB រាវប៉ុស្តិ៍ចេញ ហើយស្កេនរកប៉ុស្តិ៍ថ្មីម្តងទៀត។\n\nផ្ទៀងផ្ទាត់ថាអ្នកបានដោតឧបករណ៍ USB រាវប៉ុស្តិ៍ និងបានភ្ជាប់ទៅប្រភពសញ្ញាទូរទស្សន៍\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ អ្នកប្រហែលជាត្រូវសម្រួលទីតាំង និងទិសដៅរបស់វាដើម្បីទទួលបានប៉ុស្តិ៍ច្រើនបំផុត។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងដែលខ្ពស់ក្បែរបង្អួច។"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"វានឹងលុបប៉ុស្តិ៍ដែលបានរកឃើញដោយឧបករណ៍រាវបណ្តាញ ហើយបន្ទាប់មកស្កេនរកបណ្តាញថ្មី។\n\nផ្ទៀងផ្ទាត់ថាអ្នកបានបើកអង្គរាវបណ្តាញនេះ និងបានភ្ជាប់ទៅប្រភពរលកសញ្ញាទូរទស្សន៍។\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ អ្នកត្រូវសម្រួលទីតាំង និងទិសដៅរបស់វា ដើម្បីទទួលបានប៉ុស្តិ៍ច្រើនបំផុត។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងដែលខ្ពស់ក្បែរបង្អួច។"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"បន្ត"</item>
     <item msgid="235450158666155406">"បោះបង់"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"ការដំឡើងអង្គរាវប៉ុស្តិ៍ទូរទស្សន៍"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"ការដំឡើងឧបករណ៍ USB រាវប៉ុស្តិ៍ទូរទស្សន៍"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"ការរៀបចំឧបករណ៍រាវបណ្តាញប៉ុស្តិ៍"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"វាអាចចំណាយពេលច្រើននាទី"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"អង្គរាវប៉ុស្តិ៍មិនអាចប្រើបានជាបណ្តោះអាសន្ន ឬបានប្រើសម្រាប់ការថតរួចទៅហើយ។"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"រកមិនឃើញប៉ុស្តិ៍ទេ"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"ការស្កេននេះរកមិនឃើញប៉ុស្តិ៍ណាមួយឡើយ។ សូមផ្ទៀងផ្ទាត់ថាប៉ុស្តិ៍ទូរទស្សន៍របស់អ្នកត្រូវបានភ្ជាប់ទៅប្រភពរលកសញ្ញាទូរទស្សន៍។\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ សូមសម្រួលទីតាំង ឬទិសដៅរបស់វា។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងខ្ពស់ និងនៅជិតបង្អួច បន្ទាប់មកធ្វើការស្កេនម្តងទៀត។"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"ការស្កេនរកមិនឃើញប៉ុស្តិ៍ទេ។ ផ្ទៀងផ្ទាត់ថាអ្នកបានដោតឧបករណ៍ USB រាវប៉ុស្តិ៍ និងបានភ្ជាប់ទៅប្រភពសញ្ញាទូរទស្សន៍។\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ សូមសម្រួលទីតាំង និងទិសដៅរបស់វា។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងដែលខ្ពស់ក្បែរបង្អួច ហើយបន្ទាប់មកស្កេនម្តងទៀត។"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"ការស្កេនរកមិនឃើញប៉ុស្តិ៍ណាមួយទេ។ ផ្ទៀងផ្ទាត់ថាអ្នកបានបើកឧបករណ៍រាវបណ្តាញនេះ និងបានភ្ជាប់ទៅប្រភពរលកសញ្ញាទូរទស្សន៍។\n\nប្រសិនបើអ្នកប្រើអង់តែនឥតខ្សែ សូមសម្រួលទីតាំង និងទិសដៅរបស់វា។ ដើម្បីទទួលបានលទ្ធផលល្អបំផុត សូមដាក់វានៅកន្លែងដែលខ្ពស់ក្បែរបង្អួច បន្ទាប់មកស្កេនម្តងទៀត។"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"ស្កេនម្តងទៀត"</item>
     <item msgid="2092797862490235174">"រួចរាល់"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"ស្កេនរកប៉ុស្តិ៍ទូរទស្សន៍"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"ការដំឡើងអង្គរាវប៉ុស្តិ៍ទូរទស្សន៍"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"ការដំឡើងឧបករណ៍ USB រាវប៉ុស្តិ៍ទូរទស្សន៍"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"អង្គរាវប៉ុស្តិ៍ USB សម្រាប់ទូរទស្សន៍ត្រូវបានផ្តាច់"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"ស្កេនរកប៉ុស្តិ៍ទូរទស្សន៍"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"ការរៀបចំអង្គរាវរកប៉ុស្តិ៍ទូរទស្សន៍"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"ការរៀបចំអង្គរាវរកប៉ុស្តិ៍ទូរទស្សន៍តាម USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"ការរៀបចំអង្គរាវរកបណ្តាញទូរទស្សន៍"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"អង្គរាវរកប៉ុស្តិ៍ USB សម្រាប់ទូរទស្សន៍ត្រូវបានផ្តាច់។"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"អង្គរាវរក​បណ្តាញ​ត្រូវ​បាន​ផ្ដាច់។"</string>
 </resources>
diff --git a/usbtuner-res/values-kn/strings.xml b/usbtuner-res/values-kn-rIN/strings.xml
similarity index 65%
rename from usbtuner-res/values-kn/strings.xml
rename to usbtuner-res/values-kn-rIN/strings.xml
index fb97ae2..af90346 100644
--- a/usbtuner-res/values-kn/strings.xml
+++ b/usbtuner-res/values-kn-rIN/strings.xml
@@ -19,27 +19,26 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ಟಿವಿ ಟ್ಯೂನರ್"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB ಟಿವಿ ಟ್ಯೂನರ್"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"ಆನ್"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"ಆಫ್"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"ನೆಟ್‌ವರ್ಕ್ ಟಿವಿ ಟ್ಯೂನರ್ (ಬೀಟಾ)‌‌"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"ಪ್ರಕ್ರಿಯೆಗೊಳಿಸುವುದನ್ನು ಪೂರೈಸಲು ದಯವಿಟ್ಟು ಕಾಯಿರಿ"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"ನಿಮ್ಮ ಚಾನಲ್ ಮೂಲವನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"ಯಾವುದೇ ಸಂಕೇತವಿಲ್ಲ"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> ಗೆ ಟ್ಯೂನ್ ಮಾಡುವಲ್ಲಿ ವಿಫಲವಾಗಿದೆ"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ಟ್ಯೂನ್ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ಟ್ಯೂನರ್ ಸಾಫ್ಟ್‌ವೇರ್‍ ಅನ್ನು ಇತ್ತೀಚಿಗೆ ಅಪ್‌ಡೇಟ್ ಮಾಡಲಾಗಿದೆ. ದಯವಿಟ್ಟು ಚಾನಲ್‌ಗಳನ್ನು ಮರು-ಸ್ಕ್ಯಾನ್‌ ಮಾಡಿ."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ಆಡಿಯೊ ಸಕ್ರಿಯಗೊಳಿಸಲು ಸಿಸ್ಟಂ ಧ್ವನಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಸರೌಂಡ್ ಧ್ವನಿಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"ಆಡಿಯೊವನ್ನು ಪ್ಲೇ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಬೇರೊಂದು ಟಿವಿಯಲ್ಲಿ ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"ಚಾನಲ್ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"ಟಿವಿ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB ಚಾನಲ್ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
-    <string name="bt_setup_new_description" msgid="256690722062003128">"ನಿಮ್ಮ ಟಿವಿಯನ್ನು ಟಿವಿ ಸಿಗ್ನಲ್‌ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಾನ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ."</string>
-    <string name="ut_setup_new_description" msgid="2610122936163002137">"USB ಟ್ಯೂನಲ್ ಅನ್ನು ಪ್ಲಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಾನ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ."</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"ನೆಟ್‌ವರ್ಕ್ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
+    <string name="bt_setup_new_description" msgid="256690722062003128">"ನಿಮ್ಮ ಟಿವಿಯನ್ನು ಟಿವಿ ಸಿಗ್ನಲ್‌ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಳ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ."</string>
+    <string name="ut_setup_new_description" msgid="2610122936163002137">"USB ಟ್ಯೂನಲ್ ಅನ್ನು ಪ್ಲಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಳ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"ನೆಟ್‌ವರ್ಕ್ ಟ್ಯೂನರ್ ಆನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ನೆಟ್‌ವರ್ಕ್ ಸಂಪರ್ಕದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಳ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಅದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"ಮುಂದುವರಿಸು"</item>
     <item msgid="727245208787621142">"ಸದ್ಯಕ್ಕೆ ಬೇಡ"</item>
   </string-array>
     <string name="bt_setup_again_title" msgid="884713873101099572">"ಚಾನಲ್ ಸೆಟಪ್ ಅನ್ನು ಮರುರನ್ ಮಾಡುವುದೇ?"</string>
-    <string name="bt_setup_again_description" msgid="1247792492948741337">"ಟಿವಿ ಟ್ಯೂನರ್‌ನಿಂದ ಪತ್ತೆ ಮಾಡಲಾದ ಚಾನಲ್‌ಗಳನ್ನು ಇದು ತೆಗೆದುಹಾಕುತ್ತದೆ ಹಾಗೂ ಮತ್ತೆ ಹೊಸ ಚಾನಲ್‌ಗಳಿಗೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತದೆ.\n\nನಿಮ್ಮ ಟಿವಿಯನ್ನು ಟಿವಿ ಸಿಗ್ನಲ್‌ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಾನ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ."</string>
-    <string name="ut_setup_again_description" msgid="7837706010887799255">"USB ಟ್ಯೂನರ್‌ನಿಂದ ಪತ್ತೆ ಮಾಡಲಾದ ಚಾನಲ್‌ಗಳನ್ನು ಇದು ತೆಗೆದುಹಾಕುತ್ತದೆ ಹಾಗೂ ಮತ್ತೆ ಹೊಸ ಚಾನಲ್‌ಗಳಿಗೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತದೆ.\n\nUSB ಟ್ಯೂನಲ್ ಅನ್ನು ಪ್ಲಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಾನ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ."</string>
+    <string name="bt_setup_again_description" msgid="1247792492948741337">"ಟಿವಿ ಟ್ಯೂನರ್‌ನಿಂದ ಪತ್ತೆ ಮಾಡಲಾದ ಚಾನಲ್‌ಗಳನ್ನು ಇದು ತೆಗೆದುಹಾಕುತ್ತದೆ ಹಾಗೂ ಮತ್ತೆ ಹೊಸ ಚಾನಲ್‌ಗಳಿಗೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತದೆ.\n\nನಿಮ್ಮ ಟಿವಿಯನ್ನು ಟಿವಿ ಸಿಗ್ನಲ್‌ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಳ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ."</string>
+    <string name="ut_setup_again_description" msgid="7837706010887799255">"USB ಟ್ಯೂನರ್‌ನಿಂದ ಪತ್ತೆ ಮಾಡಲಾದ ಚಾನಲ್‌ಗಳನ್ನು ಇದು ತೆಗೆದುಹಾಕುತ್ತದೆ ಹಾಗೂ ಮತ್ತೆ ಹೊಸ ಚಾನಲ್‌ಗಳಿಗೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತದೆ.\n\nUSB ಟ್ಯೂನಲ್ ಅನ್ನು ಪ್ಲಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಳ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"ನೆಟ್‌ವರ್ಕ್ ಟ್ಯೂನರ್‌ನಿಂದ ಪತ್ತೆ ಮಾಡಲಾದ ಚಾನಲ್‌ಗಳನ್ನು ಇದು ತೆಗೆದುಹಾಕುತ್ತದೆ ಹಾಗೂ ಮತ್ತೆ ಹೊಸ ಚಾನಲ್‌ಗಳಿಗೆ ಸ್ಕ್ಯಾನ್ ಮಾಡುತ್ತದೆ.\n\nನೆಟ್‌ವರ್ಕ್ ಟ್ಯೂನಲ್ ಅನ್ನು ಆನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ನೆಟ್‌ವರ್ಕ್ ಸಂಪರ್ಕದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಹೆಚ್ಚಿನ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ವೀಕರಿಸಲು ನೀವು ಅದರ ಸ್ಥಳ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಬೇಕಾಗಬಹುದು. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಅದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"ಮುಂದುವರಿಸು"</item>
     <item msgid="235450158666155406">"ರದ್ದುಮಾಡಿ"</item>
@@ -54,13 +53,14 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"ಟಿವಿ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB ಚಾನಲ್ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"ನೆಟ್‌ವರ್ಕ್ ಚಾನಲ್ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"ಇದಕ್ಕೆ ಹಲವಾರು ನಿಮಿಷಗಳು ತೆಗೆದುಕೊಳ್ಳಬಹುದು"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ಟ್ಯೂನರ್ ತಾತ್ಕಾಲಿಕವಾಗಿ ಲಭ್ಯವಿಲ್ಲ ಅಥವಾ ಈಗಾಗಲೇ ರೆಕಾರ್ಡಿಂಗ್‌ಗೆ ಬಳಸಲಾಗಿದೆ."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
       <item quantity="one">%1$d ಚಾನಲ್‌ಗಳು ಕಂಡುಬಂದಿವೆ</item>
       <item quantity="other">%1$d ಚಾನಲ್‌ಗಳು ಕಂಡುಬಂದಿವೆ</item>
     </plurals>
-    <string name="ut_stop_channel_scan" msgid="566811986747774193">"ಚಾನಲ್ ಸ್ಕ್ಯಾನ್ ಮಾಡುವುದನ್ನು ನಿಲ್ಲಿಸು"</string>
+    <string name="ut_stop_channel_scan" msgid="566811986747774193">"ಚಾನಲ್ ಸ್ಕ್ಯಾನ್ ಮಾಡುವುದನ್ನು ನಿಲ್ಲಿಸಿ"</string>
     <plurals name="ut_result_found_title" formatted="false" msgid="1448908152026339099">
       <item quantity="one">%1$d ಚಾನಲ್‌ಗಳು ಕಂಡುಬಂದಿವೆ</item>
       <item quantity="other">%1$d ಚಾನಲ್‌ಗಳು ಕಂಡುಬಂದಿವೆ</item>
@@ -75,13 +75,16 @@
   </string-array>
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"ಯಾವುದೇ ಚಾನಲ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"ಸ್ಕ್ಯಾನ್ ಯಾವುದೇ ಚಾನಲ್‌ಗಳನ್ನು ಪತ್ತೆ ಮಾಡಿಲ್ಲ. ನಿಮ್ಮ ಟಿವಿಯನ್ನು ಟಿವಿ ಸಿಗ್ನಲ್‌ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಇದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ."</string>
-    <string name="ut_result_not_found_description" msgid="1080746285957681414">"ಸ್ಕ್ಯಾನ್ ಯಾವುದೇ ಚಾನಲ್‌ಗಳನ್ನು ಪತ್ತೆ ಮಾಡಿಲ್ಲ. USB ಟ್ಯೂನಲ್ ಅನ್ನು ಪ್ಲಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಅದರ ಸ್ಥಾನ ಅಥವಾ ದಿಕ್ಕನ್ನು ಸರಿಹೊಂದಿಸಿ. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ."</string>
+    <string name="ut_result_not_found_description" msgid="1080746285957681414">"ಸ್ಕ್ಯಾನ್ ಯಾವುದೇ ಚಾನಲ್‌ಗಳನ್ನು ಪತ್ತೆ ಮಾಡಿಲ್ಲ. USB ಟ್ಯೂನಲ್ ಅನ್ನು ಪ್ಲಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೆ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nಪ್ರಸಾರದ ಮೂಲಕ ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಅದರ ಸ್ಥಳ ಅಥವಾ ದಿಕ್ಕನ್ನು ಸರಿಹೊಂದಿಸಿ. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ ಹಾಗೂ ಮತ್ತೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"ಸ್ಕ್ಯಾನ್ ನಂತರ ಯಾವುದೇ ಚಾನಲ್ ಕಂಡುಬಂದಿಲ್ಲ. ನೆಟ್‌ವರ್ಕ್ ಟ್ಯೂನರ್ ಆನ್ ಮಾಡಲಾಗಿದೆಯೇ ಮತ್ತು ಟಿವಿ ಸಿಗ್ನಲ್ ಮೂಲಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ.\n\nನೀವು ನೆಟ್‌ವರ್ಕ್ ಸಂಪರ್ಕದ ಮೂಲಕ  ಆಂಟೆನಾ ಬಳಸುತ್ತಿದ್ದರೆ, ಅದರ ಸ್ಥಳ ಅಥವಾ ದಿಕ್ಕನ್ನು ಹೊಂದಿಸಿ. ಉತ್ತಮ ಫಲಿತಾಂಶಗಳಿಗೆ, ಅದನ್ನು ಎತ್ತರದಲ್ಲಿ ಮತ್ತು ಕಿಟಕಿಯ ಬಳಿ ಇರಿಸಿ ಹಾಗೂ ಮತ್ತೊಮ್ಮೆ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"ಮತ್ತೆ ಸ್ಕ್ಯಾನ್ ಮಾಡು"</item>
     <item msgid="2092797862490235174">"ಮುಗಿದಿದೆ"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"ಟಿವಿ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"ಟಿವಿ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB ಟಿವಿ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB ಟಿವಿ ಟ್ಯೂನರ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"ಟಿವಿ ಚಾನಲ್‌ಗಳನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಿ"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"ಟಿವಿ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB ಟಿವಿ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"ನೆಟ್‌ವರ್ಕ್ ಟಿವಿ ಟ್ಯೂನರ್ ಸೆಟಪ್"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB ಟಿವಿ ಟ್ಯೂನರ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"ನೆಟ್‌ವರ್ಕ್ ಟ್ಯೂನರ್ ಸಂಪರ್ಕ ಕಡಿತಗೊಂಡಿದೆ."</string>
 </resources>
diff --git a/usbtuner-res/values-ko/strings.xml b/usbtuner-res/values-ko/strings.xml
index 2c67ab6..fa5b6e6 100644
--- a/usbtuner-res/values-ko/strings.xml
+++ b/usbtuner-res/values-ko/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV 튜너"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV 튜너"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"사용"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"사용 안함"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"네트워크 TV 튜너(BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"처리가 완료될 때까지 기다려 주세요."</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"채널 소스 선택"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"신호 없음"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g>에 맞추지 못함"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"조정 실패"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"튜너 소프트웨어가 최근 업데이트되었습니다. 채널을 다시 스캔하세요."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"오디오를 사용하려면 시스템 사운드 설정에서 서라운드 사운드를 사용 설정하세요."</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"오디오를 재생할 수 없습니다. 다른 TV를 사용해 보세요."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"채널 튜너 설정"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV 튜너 설정"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB 채널 튜너 설정"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"네트워크 튜너 설정"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"TV가 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용하는 경우 대부분의 채널을 수신하려면 위치나 방향을 조정해야 할 수도 있습니다. 안테나를 창가 가까이에 높게 설치하면 가장 좋습니다."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB 튜너가 전원 및 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용 중인 경우 안테나 위치나 방향을 조정하세요. 창가 가까이에 높게 설치하면 가장 좋습니다."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"네트워크 튜너의 전원이 켜져 있고 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용하는 경우 안테나 위치나 방향을 조정하세요. 최상의 결과를 얻으려면 안테나를 창가 가까이에 높게 설치하세요."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"계속"</item>
     <item msgid="727245208787621142">"나중에"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"채널 설정을 다시 실행하시겠습니까?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"이렇게 하면 TV 튜너에서 찾은 채널을 삭제하고 새로운 채널을 다시 스캔하게 됩니다.\n\nTV가 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용하는 경우 대부분의 채널을 수신하려면 위치나 방향을 조정해야 할 수 있습니다. 안테나를 창가 가까이에 높게 설치하면 가장 좋습니다."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"이 작업을 수행하면 USB 튜너에서 찾은 채널이 삭제되며 새로운 채널을 다시 스캔합니다.\n\nUSB 튜너가 전원 및 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용 중인 경우 안테나 위치나 방향을 조정하세요. 창가 가까이에 높게 설치하면 가장 좋습니다."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"네트워크 튜너에서 찾은 채널이 삭제되며 새로운 채널을 다시 스캔합니다.\n\n네트워크 튜너의 전원이 켜져 있고 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용하는 경우 안테나 위치나 방향을 조정하세요. 최상의 결과를 얻으려면 안테나를 창가 가까이에 높게 설치하고 다시 스캔해보세요."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"계속"</item>
     <item msgid="235450158666155406">"취소"</item>
@@ -54,8 +53,9 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV 튜너 설정"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB 채널 튜너 설정"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"네트워크 채널 튜너 설정"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"이 작업은 몇 분 정도 걸릴 수 있습니다."</string>
-    <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"일시적으로 튜너를 사용할 수 없거나 녹화에서 이미 사용하고 있습니다."</string>
+    <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"일시적으로 튜너를 사용할 수 없거나 이미 녹화에 사용하고 있습니다."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
       <item quantity="other">채널 %1$d개 발견</item>
       <item quantity="one">채널 %1$d개 발견</item>
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"채널 없음"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"스캔 결과 채널을 찾지 못했습니다. TV가 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용하는 경우 위치나 방향을 조정하세요. 안테나를 창가 가까이에 높게 설치하면 가장 좋습니다."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"스캔하여 채널을 찾을 수 없습니다. USB 튜너가 전원 및 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용 중인 경우 안테나 위치나 방향을 조정하세요. 창가 가까이에 높게 설치하면 가장 좋습니다. 그런 다음 다시 스캔해 보세요."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"스캔 결과 채널을 찾지 못했습니다. 네트워크 튜너의 전원이 켜져 있고 TV 신호 소스에 연결되어 있는지 확인하세요.\n\n무선 안테나를 사용하는 경우 안테나 위치나 방향을 조정하세요. 최상의 결과를 얻으려면 안테나를 창가 가까이에 높게 설치하고 다시 스캔해보세요."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"다시 스캔"</item>
     <item msgid="2092797862490235174">"완료"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"TV 채널 스캔"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV 튜너 설정"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV 튜너 설정"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV 튜너 연결 끊어짐"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TV 채널 스캔"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV 튜너 설정"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV 튜너 설정"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"네트워크 TV 튜너 설정"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV 튜너의 연결이 끊겼습니다."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"네트워크 튜너의 연결이 끊겼습니다."</string>
 </resources>
diff --git a/usbtuner-res/values-ky/strings.xml b/usbtuner-res/values-ky-rKG/strings.xml
similarity index 73%
rename from usbtuner-res/values-ky/strings.xml
rename to usbtuner-res/values-ky-rKG/strings.xml
index 39e9d1d..1811822 100644
--- a/usbtuner-res/values-ky/strings.xml
+++ b/usbtuner-res/values-ky-rKG/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Сыналгы күүлөгүчү"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB сыналгы күүлөгүчү"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Күйүк"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Өчүк"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Тармактык ТВ-тюнер (БЕТА)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Иштетүүнү бүтүрүү үчүн күтө туруңуз"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Каналыңыздын булагын тандаңыз"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Сигнал жок"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> каналы кармалган жок"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Канал кармалбай койду"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Күүлөгүчтүн программасы жакында жаңыртылды. Каналдарды кайрадан издеңиз."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Каналдын үнүн чыгаруу үчүн тутумдун үн жөндөөлөрүнө өтүп, көлөмдүү добушту иштетүү керек"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Аудио ойнотулбай жатат. Башка каналды байкап көрүңүз"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Канал күүлөгүчтү жөндөө"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Сыналгынын күүлөгүчүн жөндөө"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB канал күүлөгүчүнүн жөндөөсү"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Тармактык тюнерди жөндөө"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Сыналдыңыз сыналгынын сигнал булагына туташтырылганын текшериңиз. \n\nЭгер телеантенна колдонулуп жатса, анын ордун же багытын тууралаңыз. Мыкты кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеңиз."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB күүлөгүч сайылып турганын жана сыналгынын сигнал булагына туташтырылганын текшериңиз.\n\nЭгер телеантенна колдонулуп жатса, көпчүлүк каналдарды табуу үчүн анын ордун же багытын тууралашыңыз керек болот. Мыкты кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеңиз."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Тармактык тюнер сайылып турганын жана сыналгынын сигнал булагына туташтырылганын текшериңиз.\n\nЭгер телеантенна колдонулуп жатса, каналдарды табуу үчүн анын ордун же багытын тууралашыңыз керек болот. Антенна жакшы кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеп көрүңүз."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Улантуу"</item>
     <item msgid="727245208787621142">"Азыр эмес"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Канал кайра жөндөлсүнбү?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Ушуну менен сыналгынын күүлөгүчүнөн табылган каналдар алынып салынып, жаңы каналдар кайра изделет.\n\nСыналдыңыз сыналгынын сигнал булагына туташтырылганын текшериңиз.\n\nIЭгер телеантенна колдонулуп жатса, көпчүлүк каналдарды табуу үчүн анын ордун же багытын тууралашыңыз керек болот. Мыкты кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеңиз."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Ушуну менен USB күүлөгүчтөн табылган каналдар алынып салынып, жаңы каналдар кайра изделет.\n\nUSB күүлөгүч сайылып турганын жана сыналгынын сигнал булагына туташтырылганын текшериңиз.\n\nЭгер телеантенна колдонулуп жатса, көпчүлүк каналдарды табуу үчүн анын ордун же багытын тууралашыңыз керек болот. Мыкты кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеңиз."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Ушуну менен тармактык тюнер аркылуу табылган каналдар алынып салынып, жаңы каналдар кайра изделет.\n\nТармактык тюнер сайылып турганын жана сыналгынын сигнал булагына туташтырылганын текшериңиз.\n\nЭгер телеантенна колдонулуп жатса, каналдарды табуу үчүн анын ордун же багытын тууралашыңыз керек болот. Антенна жакшы кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеп көрүңүз."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Улантуу"</item>
     <item msgid="235450158666155406">"Токтотуу"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Сыналгы күүлөгүчүн жөндөө"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB канал күүлөгүчүн жөндөө"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Тармактык каналдын тюнерин жөндөө"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Бир нече мүнөт созулушу мүмкүн"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Тюнер убактылуу жеткиликсиз же жаздыруу үчүн колдонулууда."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Бир да канал табылган жок"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Издөөдөн эч бир канал табылган жок. Сыналдыңыз сыналгынын сигнал булагына туташтырылганын текшериңиз.\n\nЭгер телеантенна колдонулуп жатса, анын ордун же багытын тууралаңыз. Мыкты кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеңиз."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Издөөдөн эч бир канал табылган жок. USB күүлөгүч сайылып турганын жана сыналгынын сигнал булагына туташтырылганын текшериңиз.\n\nЭгер телеантенна колдонулуп жатса, анын ордун же багытын тууралаңыз. Мыкты кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеңиз."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Каналдар табылган жок. Тармактык тюнер сайылып турганын жана сыналгынын сигнал булагына туташтырылганын текшериңиз.\n\nЭгер телеантенна колдонулуп жатса, анын ордун же багытын тууралаңыз. Антенна жакшы кармашы үчүн аны бийик жана терезеге жакын жерге коюп, кайра издеп көрүңүз."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Кайра издөө"</item>
     <item msgid="2092797862490235174">"Бүттү"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Сыналгы каналдарын издөө"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Сыналгы күүлөгүчүн жөндөө"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB күүлөгүчүнүн жөндөөсү"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV күүлөгүчү ажыратылды."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Сыналгы каналдарын издөө"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"ТВ-тюнерди жөндөө"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB ТВ-тюнерин жөндөө"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Тармактык ТВ-тюнерди жөндөө"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV күүлөгүчү ажыратылды."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Тармак күүлөгүчү ажыратылды."</string>
 </resources>
diff --git a/usbtuner-res/values-lo/strings.xml b/usbtuner-res/values-lo-rLA/strings.xml
similarity index 73%
rename from usbtuner-res/values-lo/strings.xml
rename to usbtuner-res/values-lo-rLA/strings.xml
index 954baab..306576a 100644
--- a/usbtuner-res/values-lo/strings.xml
+++ b/usbtuner-res/values-lo-rLA/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ຕົວຮັບສັນຍານໂທລະພາບ"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"ຕົວຮັບສັນຍານໂທລະພາບ USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"ເປີດ"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"ປິດ"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (ເບຕ້າ)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"ກະລຸນາລໍຖ້າເພື່ອປະມວນຜົນໃຫ້ສຳເລັດ"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"ເລືອກແຫຼ່ງສັນຍານຊ່ອງຂອງທ່ານ"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"ບໍ່ມີສັນຍານ"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"ປັບຫາ <xliff:g id="CHANNEL_NAME">%s</xliff:g> ບໍ່ສຳເລັດ"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ປັບຊ່ອງບໍ່ສຳເລັດ"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ຊອບແວຕົວປັບສັນຍານໄດ້ຮັບການອັບເດດເມື່ອບໍ່ດົນມານີ້ແລ້ວ. ກະລຸນາສະແກນຫາຊ່ອງຄືນໃໝ່."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ເປີດໃຊ້ສຽງຮອບທິດທາງໃນການຕັ້ງຄ່າລະບົບສຽງເພື່ອເປີດໃຊ້ສຽງ."</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Cannot play audio. Please try another TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"ຕັ້ງເຄື່ອງຮັບສັນຍານຊ່ອງ"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"ຕັ້ງຄ່າຕົວຮັບສັນຍານໂທລະພາບ"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"ຕັ້ງເຄື່ອງຮັບສັນຍານຊ່ອງ USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Network tuner setup"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"ໃຫ້ກວດສອບວ່າທ່ານເຊື່ອມຕໍ່ໂທລະພາບຂອງທ່ານຫາແຫລ່ງສັນຍານໂທລະພາບແລ້ວ.\n\nຫາກໃຊ້ເສົາອາກາດ, ໃຫ້ຍ້າຍບ້ອນວາງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນທີ່ດີທີ່ສຸດ, ໃຫ້ວາງໄວ້ບ່ອນສູງໃກ້ໆປ່ອງຢ້ຽມ ແລ້ວລອງສະແກນໃໝ່."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"ກວດສອບເບິ່ງເຄື່ອງຮັບສັນຍານ USB ວ່າ ໄດ້ສຽບສາຍ ແລະ ເຊື່ອມຕໍ່ກັບແຫຼ່ງສັນຍານໂທລະພາບແລ້ວຫຼືຍັງ.\n\nຫາກໃຊ້ເສົາອາກາດ, ໃຫ້ຍ້າຍບ້ອນວາງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນທີ່ດີທີ່ສຸດ, ໃຫ້ວາງໄວ້ບ່ອນສູງໃກ້ໆປ່ອງຢ້ຽມ ແລ້ວລອງສະແກນໃໝ່."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"ກວດສອບເບິ່ງເຄື່ອງຮັບສັນຍານເຄືອຂ່າຍວ່າ ໄດ້ສຽບສາຍ ແລະ ເຊື່ອມຕໍ່ກັບແຫຼ່ງສັນຍານໂທລະພາບແລ້ວຫຼືຍັງ.\n\nຫຼຫາກໃຊ້ເສົາອາກາດ, ໃຫ້ຍ້າຍບ່ອນວາງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນທີ່ດີທີ່ສຸດ, ໃຫ້ວາງໄວ້ບ່ອນສູງໃກ້ໆປ່ອງຢ້ຽມ ແລ້ວລອງສະແກນໃໝ່."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"ສືບຕໍ່"</item>
     <item msgid="727245208787621142">"ບໍ່ແມ່ນຕອນນີ້"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"ຕັ້ງຄ່າຊ່ອງຄືນໃໝ່ບໍ່?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"ນີ້ເປັນການລຶບຊ່ອງທີ່ພົບແລ້ວອອກໄປຈາກຕົວຮັບສັນຍານໂທລະພາບ ແລະ ສະແກນຫາຊ່ອງໃໝ່ອີກຄັ້ງ.\n\nກວດສອບເບິ່ງຕົວຮັບສັນຍານໂທລະພາບວ່າໄດ້ສຽບສາຍ ແລະ ເຊື່ອມຕໍ່ກັບແຫຼ່ງສັນຍານໂທລະພາບແລ້ວຫຼືຍັງ.\n\nຫາກໃຊ້ເສົາອາກາດ, ໃຫ້ຍ້າຍບ້ອນວາງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນທີ່ດີທີ່ສຸດ, ໃຫ້ວາງໄວ້ບ່ອນສູງໃກ້ໆປ່ອງຢ້ຽມ ແລ້ວລອງສະແກນໃໝ່."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"ນີ້ຈະເປັນການລຶບຊ່ອງທີ່ພົບແລ້ວອອກໄປຈາກເຄື່ອງຮັບສັນຍານ USB ແລະ ສະແກນຫາຊ່ອງໃໝ່ອີກ.\n\nໃຫ້ກວດສອບເບິ່ງເຄື່ອງຮັບສັນຍານ USB ວ່າ ໄດ້ສຽບສາຍ ແລະ ເຊື່ອມຕໍ່ກັບແຫຼ່ງສັນຍານໂທລະພາບແລ້ວຫຼືຍັງ.\n\nຫາກໃຊ້ເສົາອາກາດ, ໃຫ້ຍ້າຍບ້ອນວາງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນທີ່ດີທີ່ສຸດ, ໃຫ້ວາງໄວ້ບ່ອນສູງໃກ້ໆປ່ອງຢ້ຽມ ແລ້ວລອງສະແກນໃໝ່."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"ນີ້ຈະເປັນການລຶບຊ່ອງທີ່ພົບແລ້ວອອກໄປຈາກເຄື່ອງຮັບສັນຍານເຄືອຂ່າຍ ແລະ ສະແກນຫາຊ່ອງໃໝ່ອີກຄັ້ງ.\n\nໃຫ້ກວດສອບເບິ່ງເຄື່ອງຮັບສັນຍານເຄືອຂ່າຍວ່າໄດ້ສຽບສາຍ ແລະ ເຊື່ອມຕໍ່ກັບແຫຼ່ງສັນຍານໂທລະພາບແລ້ວຫຼືຍັງ.\n\nຫາກໃຊ້ເສົາອາກາດ, ທ່ານອາດຈະຕ້ອງໄດ້ປັບການຕັ້ງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນດີຂຶ້ນ, ວາງມັນໄວ້ສູງ ແລະ ໃກ້ກັບປ່ອງຢ້ຽມແລ້ວສະແກນໃໝ່ອີກຄັ້ງ."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"ສືບຕໍ່"</item>
     <item msgid="235450158666155406">"ຍົກເລີກ"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"ຕັ້ງຄ່າຕົວຮັບສັນຍານໂທລະພາບ"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"ການຕັ້ງເຄື່ອງຮັບສັນຍານຊ່ອງ USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"ຕັ້ງຄ່າຕົວຈູນສັນຍານຊ່ອງເຄືອຂ່າຍ"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"ຂັ້ນຕອນນີ້ອາດຈະໃຊ້ເວລາຫຼາຍນາທີ"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ຈູນເນີບໍ່ສາມາດໃຊ້ໄດ້ຊົ່ວຄາວ ຫຼື ຖືກໃຊ້ໂດຍການບັນທຶກໃດໜຶ່ງຢູ່ກ່ອນແລ້ວ."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"ບໍ່ພົບຊ່ອງໃດ"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"ການສະແກນບໍ່ພົບຊ່ອງໃດໆເລີຍ. ໃຫ້ຢັ້ງຢືນວ່າທ່ານເຊື່ອມຕໍ່ໂທລະພາບຂອງທ່ານຫາແຫລ່ງສັນຍານໂທລະພາບແລ້ວ.\n\nຫາກໃຊ້ເສົາອາກາດ, ໃຫ້ຍ້າຍບ້ອນວາງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນທີ່ດີທີ່ສຸດ, ໃຫ້ວາງໄວ້ບ່ອນສູງໃກ້ໆປ່ອງຢ້ຽມ ແລ້ວລອງສະແກນໃໝ່."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"ການສະແກນບໍ່ພົບຊ່ອງໃດ. ໃຫ້ກວດສອບເບິ່ງເຄື່ອງຮັບສັນຍານ USB ວ່າໄດ້ສຽບສາຍ ແລະ ເຊື່ອມຕໍ່ກັບແຫຼ່ງສັນຍານໂທລະພາບແລ້ວຫຼືຍັງ.\n\nຫາກໃຊ້ເສົາອາກາດ, ໃຫ້ຍ້າຍບ້ອນວາງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນທີ່ດີທີ່ສຸດ, ໃຫ້ວາງໄວ້ບ່ອນສູງໃກ້ໆປ່ອງຢ້ຽມ ແລ້ວລອງສະແກນໃໝ່."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"ການສະແກນບໍ່ພົບຊ່ອງໃດ. ໃຫ້ກວດສອບເບິ່ງເຄື່ອງຮັບສັນຍານເຄືອຂ່າຍວ່າໄດ້ສຽບສາຍ ແລະ ເຊື່ອມຕໍ່ກັບແຫຼ່ງສັນຍານໂທລະພາບແລ້ວຫຼືຍັງ.\n\nຫາກໃຊ້ເສົາອາກາດ, ໃຫ້ຍ້າຍບ້ອນວາງ ຫຼື ທິດທາງຂອງມັນ. ເພື່ອໃຫ້ໄດ້ຜົນທີ່ດີທີ່ສຸດ, ໃຫ້ວາງໄວ້ບ່ອນສູງໃກ້ໆປ່ອງຢ້ຽມ ແລ້ວລອງສະແກນໃໝ່."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"ສະແກນອີກ"</item>
     <item msgid="2092797862490235174">"ແລ້ວໆ"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"ສະແກນຫາຊ່ອງໂທລະພາບ"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"ຕັ້ງຄ່າຕົວຮັບສັນຍານໂທລະພາບ"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"ຕັ້ງຄ່າຕົວຮັບສັນຍານໂທລະພາບແບບ USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"ການເຊື່ອມຕໍ່ USB TV tuner ຖືກຕັດແລ້ວ."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"ສະແກນຫາຊ່ອງໂທລະທັດ"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"ຕັ້ງຄ່າຕົວຮັບສັນຍານໂທລະທັດ"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"ຕັ້ງຄ່າຕົວຮັບສັນຍານໂທລະທັດແບບ USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"ຕັ້ງຄ່າຕົວຮັບສັນຍານໂທລະທັດເຄືອຂ່າຍ"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"ຕັດການເຊື່ອມຕໍ່ USB TV tuner ແລ້ວ."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"ຕັດການເຊື່ອມຕໍ່ຕົວຈູນສັນຍານເຄືອຂ່າຍແລ້ວ."</string>
 </resources>
diff --git a/usbtuner-res/values-lt/strings.xml b/usbtuner-res/values-lt/strings.xml
index 3ce2efc..c55020b 100644
--- a/usbtuner-res/values-lt/strings.xml
+++ b/usbtuner-res/values-lt/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV imtuvas"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV imtuvas"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Įjungta"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Išjungti"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Tinklo TV imtuvas (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Palaukite, kol baigsis apdorojimas"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Pasirinkite kanalo šaltinį"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Nėra signalo"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Nepavyko įjungti kanalo „<xliff:g id="CHANNEL_NAME">%s</xliff:g>“"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Nepavyko suderinti"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Imtuvo programinė įranga buvo neseniai atnaujinta. Iš naujo nuskaitykite kanalus."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Įgalinkite erdvinį garsą sistemos garso nustatymuose, kad galėtumėte įgalinti garsą"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Negalima paleisti garso įrašo. Bandykite naudoti kitą TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kanalų imtuvo sąranka"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV imtuvo sąranka"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB kanalų imtuvo sąranka"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Tinklo imtuvo sąranka"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Įsitikinkite, kad jūsų TV prijungtas prie TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Įsitikinkite, kad USB imtuvas prijungtas prie maitinimo ir TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį, kad būtų rodoma kuo daugiau kanalų. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Įsitikinkite, kad tinklo imtuvas yra įjungtas ir prijungtas prie TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango ir nuskaitykite dar kartą."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Tęsti"</item>
     <item msgid="727245208787621142">"Ne dabar"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Iš naujo vykdyti kanalų sąranką?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Tai atlikus bus pašalinti kanalai, kuriuos aptiko TV imtuvas, ir bus vėl ieškoma naujų kanalų.\n\nNuskaičius nerasta jokių kanalų. Įsitikinkite, kad jūsų TV prijungtas prie TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Taip bus pašalinti rasti kanalai iš USB imtuvo ir nauji kanalai nuskaityti dar kartą.\n\nĮsitikinkite, kad USB imtuvas prijungtas prie maitinimo ir TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį, kad būtų rodoma kuo daugiau kanalų. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Atlikus šį veiksmą iš tinklo imtuvo bus pašalinti rasti kanalai ir bus dar kartą nuskaitoma ieškant naujų kanalų.\n\nĮsitikinkite, kad tinklo imtuvas yra įjungtas ir prijungtas prie TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango ir nuskaitykite dar kartą."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Tęsti"</item>
     <item msgid="235450158666155406">"Atšaukti"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV imtuvo sąranka"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB kanalų imtuvo sąranka"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Tinklo kanalų imtuvo sąranka"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Tai gali užtrukti kelias minutes"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Derintuvas laikinai nepasiekiamas arba jau yra naudojamas įrašant."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -82,12 +82,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nerasta kanalų"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Nuskaičius nerasta jokių kanalų. Įsitikinkite, kad jūsų TV prijungtas prie TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango ir nuskaitykite dar kartą."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Nuskaitant nerasta kanalų. Patvirtinkite, ar USB imtuvas prijungtas prie TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango ir nuskaitykite dar kartą."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Nuskaičius nerasta jokių kanalų. Įsitikinkite, kad tinklo imtuvas yra įjungtas ir prijungtas prie TV signalo šaltinio.\n\nJei naudojate belaidę anteną, koreguokite jos vietą arba kryptį. Kad pasiektumėte geriausių rezultatų, ją padėkite aukštai prie lango ir nuskaitykite dar kartą."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Nuskaityti dar kartą"</item>
     <item msgid="2092797862490235174">"Atlikta"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Vykdykite TV kanalų nuskaitymą"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV imtuvo sąranka"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV imtuvo sąranka"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV imtuvas atjungtas."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Nuskaitykite TV kanalus"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV imtuvo sąranka"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV imtuvo sąranka"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Tinklo TV imtuvo sąranka"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV imtuvas atjungtas."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Tinklo imtuvas atjungtas."</string>
 </resources>
diff --git a/usbtuner-res/values-lv/strings.xml b/usbtuner-res/values-lv/strings.xml
index 9337e7b..df910fa 100644
--- a/usbtuner-res/values-lv/strings.xml
+++ b/usbtuner-res/values-lv/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV kanālu meklētājs"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV kanālu meklētājs"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Ieslēgta"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Izslēgta"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Interneta TV kanālu meklētājs (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Lūdzu, uzgaidiet, līdz tiks pabeigta apstrāde!"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Atlasiet kanāla avotu"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Nav signāla"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Neizdevās atrast kanālu <xliff:g id="CHANNEL_NAME">%s</xliff:g>."</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Neizdevās atrast"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Nesen tika atjaunināta kanālu meklētāja programmatūra. Lūdzu, atkārtoti meklējiet kanālus."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Lai ieslēgtu audio, sistēmas skaņas iestatījumos iespējojiet ieskaujošo skaņu."</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Nevar atskaņot audio. Lūdzu, izmantojiet citu televizoru."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kanālu meklētāja iestatīšana"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV kanālu meklētāja iestatīšana"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB kanālu meklētāja iestatīšana"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Interneta kanālu meklētāja iestatīšana"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Pārbaudiet, vai televizors ir pievienots TV signāla avotam.\n\nJa izmantojat bezvadu antenu, iespējams, būs jāmaina tās novietojums vai virziens, lai uztvertu lielāko daļu kanālu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Pārbaudiet, vai USB kanālu meklētājs ir pievienots strāvas avotam un TV signāla avotam.\n\nJa izmantojat bezvadu antenu, mainiet tās novietojumu un virzienu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga un atkārtojiet kanālu meklēšanu."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Pārbaudiet, vai interneta kanālu meklētājs ir ieslēgts un pievienots TV signāla avotam.\n\nJa izmantojat bezvadu antenu, iespējams, jāmaina tās novietojums vai virziens, lai uztvertu lielāko daļu kanālu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Turpināt"</item>
     <item msgid="727245208787621142">"Vēlāk"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Vai atkārtot kanālu iestatīšanu?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Šādi no TV kanālu meklētāja tiks noņemti atrastie kanāli un tiks vēlreiz meklēti jauni kanāli.\n\nPārbaudiet, vai televizors ir pievienots TV signāla avotam.\n\nJa izmantojat bezvadu antenu, iespējams, būs jāmaina tās novietojums vai virziens, lai uztvertu lielāko daļu kanālu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Tādējādi tiks noņemti kanāli, kas tika atrasti ar USB kanālu meklētāju, un tiks atkārtota kanālu meklēšana.\n\nPārbaudiet, vai USB kanālu meklētājs ir pievienots strāvas avotam un TV signāla avotam.\n\nJa izmantojat bezvadu antenu, mainiet tās novietojumu un virzienu, lai uztvertu lielāko daļu kanālu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Šādi no interneta kanālu meklētāja tiks noņemti atrastie kanāli un tiks vēlreiz meklēti jauni kanāli.\n\nPārbaudiet, vai interneta kanālu meklētājs ir ieslēgts un pievienots TV signāla avotam.\n\nJa izmantojat bezvadu antenu, iespējams, jāmaina tās novietojums vai virziens, lai uztvertu lielāko daļu kanālu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Turpināt"</item>
     <item msgid="235450158666155406">"Atcelt"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV kanālu meklētāja iestatīšana"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB kanālu meklētāja iestatīšana"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Interneta kanālu meklētāja iestatīšana"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Tas var ilgt vairākas minūtes."</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Kanālu meklētājs īslaicīgi nav pieejams, vai arī tas jau tiek izmantots ierakstīšanai."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -79,12 +79,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Netika atrasts neviens kanāls"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Veicot meklēšanu, netika atrasts neviens kanāls. Pārbaudiet, vai televizors pievienots TV signāla avotam.\n\nJa izmantojat bezvadu antenu, mainiet tās novietojumu vai virzienu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga, bet pēc tam vēlreiz veiciet meklēšanu."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Netika atrasts neviens kanāls. Pārbaudiet, vai USB kanālu meklētājs ir pievienots strāvas avotam un TV signāla avotam.\n\nJa izmantojat bezvadu antenu, mainiet tās novietojumu un virzienu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga un atkārtojiet kanālu meklēšanu."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Netika atrasts neviens kanāls. Pārbaudiet, vai interneta kanālu meklētājs ir ieslēgts un pievienots TV signāla avotam.\n\nJa izmantojat bezvadu antenu, mainiet tās novietojumu un virzienu. Lai iegūtu labākos rezultātus, novietojiet antenu augstu pie loga un atkārtojiet kanālu meklēšanu."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Meklēt vēlreiz"</item>
     <item msgid="2092797862490235174">"Gatavs"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"TV kanālu meklēšana"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV kanālu meklētāja iestatīšana"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV kanālu meklētāja iestatīšana"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV kanālu meklētājs ir atvienots."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TV kanālu meklēšana"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV kanālu meklētāja iestatīšana"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV kanālu meklētāja iestatīšana"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Interneta TV kanālu meklētāja iestatīšana"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV kanālu meklētājs ir atvienots."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Interneta kanālu meklētājs ir atvienots."</string>
 </resources>
diff --git a/usbtuner-res/values-mk/strings.xml b/usbtuner-res/values-mk-rMK/strings.xml
similarity index 74%
rename from usbtuner-res/values-mk/strings.xml
rename to usbtuner-res/values-mk-rMK/strings.xml
index fb2e71e..2db086e 100644
--- a/usbtuner-res/values-mk/strings.xml
+++ b/usbtuner-res/values-mk-rMK/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ТВ приемник"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"ТВ приемник со USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Вклучено"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Исклучено"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Мрежен ТВ приемник (БЕТА)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Почекајте да заврши обработувањето"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Изберете го изворот на каналот"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Нема сигнал"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Не успеа да се избере <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Не успеа да се избере"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Софтверот на приемникот неодамна е ажуриран. Скенирајте ги каналите повторно."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Овозможете опкружувачки звук во поставките за звуци на системот за да овозможите аудио"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Не може да се пушти аудио. Обидете се со друг ТВ"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Поставување приемник на канали"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Поставување ТВ приемник"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Поставување на USB-приемникот за канали"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Поставување мрежен приемник"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Потврдете дека телевизорот е приклучен и поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, можеби ќе треба да ја приспособите поставеноста или насоката за да примате најмногу канали. За најдобри резултати, поставете ја високо и во близина на прозорец."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Потврдете дека USB-приемникот е приклучен и поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, можеби ќе треба да ја приспособите поставеноста или насоката за да примате најмногу канали. За најдобри резултати, поставете ја високо и во близина на прозорец."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Потврдете дека мрежниот приемник е вклучен и поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, може ќе треба да ја приспособите поставеноста или насоката за да примате најмногу канали. За најдобри резултати, поставете ја високо и во близина на прозорец."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Продолжи"</item>
     <item msgid="727245208787621142">"Не сега"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Да се изврши поставувањето на каналите повторно?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Ова ќе ги отстрани каналите од ТВ приемникот и ќе скенира за нови канали повторно.\n\nПотврдете дека телевизорот е поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, приспособете ја поставеноста или насоката. За најдобри резултати, поставете ја високо и во близина на прозорец."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Ова ќе ги отстрани каналите од USB-приемникот и ќе скенира за нови канали повторно.\n\nПотврдете дека USB-приемникот е приклучен и поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, можеби ќе треба да ја приспособите поставеноста или насоката за да примате најмногу канали. За најдобри резултати, поставете ја високо и во близина на прозорец."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Ова ќе ги отстрани каналите од мрежниот приемник и ќе скенира за нови канали повторно.\n\nПотврдете дека мрежниот приемник е вклучен и поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, може ќе треба да ја приспособите поставеноста или насоката. За најдобри резултати, поставете ја високо и во близина на прозорец."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Продолжи"</item>
     <item msgid="235450158666155406">"Откажи"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Поставување ТВ приемник"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Поставување на USB-приемникот за канали"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Поставување мрежен приемник на канали"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Ова може да трае неколку минути"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Приемникот е привремено недостапен или веќе се користи за снимање."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Не се пронајдени канали"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Скенирањето не пронајде ниеден канал. Потврдете дека телевизорот е поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, приспособете ја поставеноста или насоката. За најдобри резултати, поставете ја високо и во близина на прозорец и скенирајте повторно."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Скенирањето не пронајде ниеден канал. Потврдете дека USB-приемникот е приклучен и поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, приспособете ја поставеноста или насоката. За најдобри резултати, поставете ја високо и во близина на прозорец и скенирајте повторно."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Скенирањето не пронајде ниеден канал. Потврдете дека мрежниот приемник е вклучен и поврзан со изворот на ТВ сигналот.\n\nАко користите безжична антена, приспособете ја поставеноста или насоката. За најдобри резултати, поставете ја високо и во близина на прозорец, па скенирајте повторно."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Скенирај пак"</item>
     <item msgid="2092797862490235174">"Готово"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Скенирај ТВ-канали"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Поставување ТВ приемник"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Поставување ТВ приемник со USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"TV приемникот преку USB е исклучен."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Скенирајте ТВ-канали"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Поставување ТВ приемник"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Поставување ТВ приемник со USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Поставување мрежен ТВ приемник"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-приемникот за TV е исклучен."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Мрежниот приемник е исклучен."</string>
 </resources>
diff --git a/usbtuner-res/values-ml/strings.xml b/usbtuner-res/values-ml-rIN/strings.xml
similarity index 72%
rename from usbtuner-res/values-ml/strings.xml
rename to usbtuner-res/values-ml-rIN/strings.xml
index d025ec7..2befa74 100644
--- a/usbtuner-res/values-ml/strings.xml
+++ b/usbtuner-res/values-ml-rIN/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ടിവി ട്യൂണർ"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB ടിവി ട്യൂണർ"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"ഓണാക്കുക"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"ഓഫാക്കുക"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"നെറ്റ്‌വർക്ക് ടിവി ട്യൂണർ (ബീറ്റ)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"പ്രോസസ്സുചെയ്യൽ പൂർത്തിയാകുന്നത് വരെ കാത്തിരിക്കുക"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"നിങ്ങളുടെ ചാനൽ ഉറവിടം തിരഞ്ഞെടുക്കുക"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"സിഗ്‌നൽ ഇല്ല"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> എന്നതിലേക്ക് ട്യൂൺ ചെയ്യുന്നത് പരാജയപ്പെട്ടു"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ട്യൂൺ ചെയ്യുന്നത് പരാജയപ്പെട്ടു"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ട്യൂണർ സോഫ്‌റ്റ്‌വെയർ അടുത്തിടെ അപ്‌ഡേറ്റുചെയ്‌തു. ചാനലുകൾ വീണ്ടും സ്‌കാൻ ചെയ്യുക."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ഓഡിയോ പ്രവർത്തനക്ഷമമാക്കുന്നതിന് സിസ്റ്റം ശബ്ദ ക്രമീകരണത്തിൽ സറൗണ്ട് ശബ്‌ദം പ്രവർത്തനക്ഷമമാക്കുക"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"ഓഡിയോ പ്ലേ ചെയ്യാൻ കഴിയുന്നില്ല. മറ്റൊരു ടിവിയിൽ ശ്രമിച്ചുനോക്കൂ"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"ചാനൽ ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"ടിവി ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB ചാനൽ ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"നെറ്റ്‌വർക്ക് ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"ഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് നിങ്ങളുടെ ടിവി കണക്റ്റുചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ, പരമാവധി ചാനലുകൾ ലഭിക്കുന്നതിന്, അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കേണ്ടി വരാം. മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിക്കുക."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB ട്യൂണർ പ്ലഗിൻ ചെയ്തിട്ടുണ്ടെന്നും ഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് കണക്റ്റുചെയ്തിട്ടുണ്ടെന്നും ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ, പരമാവധി ചാനലുകൾ ലഭിക്കുന്നതിന്, അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കേണ്ടി വരാം. മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിക്കുക."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"നെറ്റ്‌വർക്ക് ട്യൂണർ ഓണാക്കിയിട്ടുണ്ടെന്നും ഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് കണക്റ്റുചെയ്തിട്ടുണ്ടെന്നും ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ, പരമാവധി ചാനലുകൾ ലഭിക്കുന്നതിന്, അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കേണ്ടി വരാം. മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിക്കുക."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"തുടരുക"</item>
     <item msgid="727245208787621142">"ഇപ്പോൾ വേണ്ട"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"ചാനൽ സജ്ജമാക്കൽ വീണ്ടും റൺ ചെയ്യണോ?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"ടിവി ട്യൂണറിൽ നിന്ന് കണ്ടെത്തിയ ചാനലുകളെ ഇത് നീക്കംചെയ്യും, പുതിയ ചാനലുകൾക്കായി വീണ്ടും സ്കാൻ ചെയ്യും.\n\nഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് നിങ്ങളുടെ ടിവി കണക്റ്റുചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ, പരമാവധി ചാനലുകൾ ലഭിക്കുന്നതിന്, അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കേണ്ടി വരാം. മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിക്കുക."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"USB ട്യൂണറിൽ നിന്ന് കണ്ടെത്തിയ ചാനലുകളെ ഇത് നീക്കംചെയ്യും, പുതിയ ചാനലുകൾക്കായി വീണ്ടും സ്കാൻ ചെയ്യും.\n\nസ്കാൻ ചെയ്തപ്പോൾ ചാനലുകളൊന്നും കണ്ടെത്തിയില്ല. USB ട്യൂണർ പ്ലഗിൻ ചെയ്തിട്ടുണ്ടെന്നും ഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് കണക്റ്റുചെയ്തിട്ടുണ്ടെന്നും ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ, പരമാവധി ചാനലുകൾ ലഭിക്കുന്നതിന്, അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കേണ്ടി വരാം. മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിക്കുക."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"നെറ്റ്‌വർക്ക് ട്യൂണറിൽ നിന്ന് കണ്ടെത്തിയ ചാനലുകളെ ഇത് നീക്കംചെയ്യും, പുതിയ ചാനലുകൾക്കായി വീണ്ടും സ്കാൻ ചെയ്യും.\n\nനെറ്റ്‌വർക്ക് ട്യൂണർ ഓണാക്കിയിട്ടുണ്ടെന്നും ഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് കണക്റ്റുചെയ്തിട്ടുണ്ടെന്നും ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ, പരമാവധി ചാനലുകൾ ലഭിക്കുന്നതിന്, അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കേണ്ടി വരാം മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിക്കുക."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"തുടരുക"</item>
     <item msgid="235450158666155406">"റദ്ദാക്കൂ"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"ടിവി ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB ചാനൽ ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"നെറ്റ്‌വർക്ക് ചാനൽ ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"ഇതിന് കുറച്ച് സമയം എടുത്തേക്കാം"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ട്യൂണർ നിലവിൽ ലഭ്യമല്ല അല്ലെങ്കിൽ ഇതിനകം തന്നെ റെക്കോർഡിംഗ് ഉപയോഗിച്ചുകൊണ്ടിരിക്കുന്നു."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"ചാനലുകളൊന്നും കണ്ടെത്തിയില്ല"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"സ്കാൻ ചെയ്തപ്പോൾ ചാനലുകളൊന്നും കണ്ടെത്തിയില്ല. ഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് നിങ്ങളുടെ ടിവി കണക്റ്റുചെയ്തിട്ടുണ്ടെന്ന് ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കുക. മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിച്ച് വീണ്ടും സ്കാൻ ചെയ്യുക."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"സ്കാൻ ചെയ്തപ്പോൾ ചാനലുകളൊന്നും കണ്ടെത്തിയില്ല. USB ട്യൂണർ പ്ലഗിൻ ചെയ്തിട്ടുണ്ടെന്നും ഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് കണക്റ്റുചെയ്തിട്ടുണ്ടെന്നും ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കുക. മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിച്ച് വീണ്ടും സ്കാൻ ചെയ്യുക."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"സ്കാൻ ചെയ്തപ്പോൾ ചാനലുകളൊന്നും കണ്ടെത്തിയില്ല. നെറ്റ്‌വർക്ക് ട്യൂണർ ഓണാക്കിയിട്ടുണ്ടെന്നും ഒരു ടിവി സിഗ്നൽ ഉറവിടത്തിലേക്ക് കണക്റ്റുചെയ്തിട്ടുണ്ടെന്നും ഉറപ്പാക്കുക.\n\nഉയരത്തിൽ വയ്ക്കേണ്ട തരത്തിലുള്ള ആന്റിനയാണ് നിങ്ങൾ ഉപയോഗിക്കുന്നതെങ്കിൽ അതിന്റെ ഇരിപ്പോ ദിശയോ ക്രമീകരിക്കുക. മികച്ച ഫലം ലഭിക്കാൻ, കുറച്ചുകൂടി ഉയരത്തിലും ജാലകത്തിന് അരികിലായും അത് സ്ഥാപിച്ച് വീണ്ടും സ്കാൻ ചെയ്യുക."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"വീണ്ടും സ്കാൻ ചെയ്യുക"</item>
     <item msgid="2092797862490235174">"പൂർത്തിയായി"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"ടിവി ചാനലുകൾക്കായി സ്കാൻ ചെയ്യുക"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"ടിവി ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB ടിവി ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB ടിവി ട്യൂണർ വിച്ഛേദിച്ചു."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"ടിവി ചാനലുകൾക്കായി സ്കാൻ ചെയ്യുക"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"ടിവി ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB ടിവി ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"നെറ്റ്‌വർക്ക് ടിവി ട്യൂണർ സജ്ജമാക്കല്‍‌"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB ടിവി ട്യൂണർ വിച്ഛേദിച്ചു."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"നെറ്റ്‌വർക്ക് ട്യൂണർ വിച്ഛേദിച്ചു."</string>
 </resources>
diff --git a/usbtuner-res/values-mn/strings.xml b/usbtuner-res/values-mn-rMN/strings.xml
similarity index 75%
rename from usbtuner-res/values-mn/strings.xml
rename to usbtuner-res/values-mn-rMN/strings.xml
index 51f7a8d..996341b 100644
--- a/usbtuner-res/values-mn/strings.xml
+++ b/usbtuner-res/values-mn-rMN/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ТВ тохируулагч"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB ТВ тохируулагч"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Идэвхтэй"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Идэвхгүй"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Сүлжээний ТВ Тохируулагч (БЭТА)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Боловсруулж дуусах хүртэл хүлээнэ үү"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Сувгийн эх үүсвэрээ сонгоно уу"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Дохио алга"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g>-д тохируулж чадсангүй"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Тохируулж чадсангүй"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Тохируулагчийн програмыг саяхан шинэчилсэн байна. Дахин суваг хайна уу."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Аудиог идэвхжүүлэхийн тулд орчны дууны системийг дууны тохиргоонд идэвхжүүлнэ үү"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Аудиог тоглуулах боломжгүй байна. Өөр ТВ дээр оролдож үзнэ үү"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Суваг тохируулагчийн тохиргоо"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"ТВ тохируулагчийн тохиргоо"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB суваг тохируулагчийн тохиргоо"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Сүлжээ тохируулагчийн тохиргоо"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"ТВ-ээ ТВ дохионы үүсвэртэй холбосон эсэхээ батална уу.\n\nХэрэв агаарын антен хэрэглэж байгаа бол олон суваг авахын тулд антены байршил эсвэл чиглэлийг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулах нь илүү үр дүнтэй."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB тохируулагчийг залгасан ба ТВ дохионы үүсвэртэй холбосон эсэхээ шалгана уу.\n\nХэрэв агаарын антен хэрэглэж байгаа бол олон суваг авахын тулд антены байршлыг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулах нь илүү үр дүнтэй байдаг."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Сүлжээ тохируулагчийг асааж, ТВ дохионы үүсвэртэй холбосон эсэхээ баталгаажуулна уу.\n\nХэрэв агаарын антен хэрэглэж байгаа бол олон суваг авахын тулд антены байршлыг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулна уу."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Үргэлжлүүлэх"</item>
     <item msgid="727245208787621142">"Одоо биш"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Сувгийн тохируулгыг дахин ажиллуулах уу?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Энэ нь ТВ тохируулагчаас олсон сувгийг устгаад, шинэ суваг хайх болно.\n\nТВ тохируулагчаа ТВ дохионы үүсвэртэй холбосон эсэхээ шалгана уу.\n\nХэрэв агаарын антен хэрэглэж байгаа бол олон суваг авахын тулд антены байршил эсвэл чиглэлийг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулах нь илүү үр дүнтэй."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Энэ нь USB тохируулагчаас олдсон сувгийг устгаад, шинэ суваг хайх болно.\n\nUSB тохируулагчийг залгасан, ТВ дохионы үүсвэртэй холбосон эсэхээ шалгана уу.\n\nХэрэв агаарын антен хэрэглэж байгаа бол олон суваг авахын тулд антены байршлыг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулах нь илүү үр дүнтэй."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Энэ нь сүлжээ тохируулагчаас олдсон сувгийг устгаж, шинэ суваг хайх болно.\n\nСүлжээ тохируулагчийг асааж, ТВ дохио үүсвэртэй холбосон эсэхээ шалгана уу.\n\nХэрэв антен хэрэглэж байгаа бол антены байршлыг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулаад, дахин хайна уу."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Үргэлжлүүлэх"</item>
     <item msgid="235450158666155406">"Цуцлах"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"ТВ тохируулагчийн тохиргоо"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB суваг тохируулагчийн тохиргоо"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Сүлжээний суваг тохируулагчийн тохиргоо"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Хэдэн минут шаардлагатай"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Суваг солигч одоогоор боломжгүй, эсвэл үүнийг өөр бичлэгт ашиглаж байна."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Суваг олсонгүй"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Хайлтын явцад суваг олсонгүй. ТВ-ээ ТВ дохионы үүсвэрт холбосон эсэхээ шалгана уу.\n\nХэрэв агаарын антен хэрэглэж байгаа бол антены байршлыг эсвэл чиглэлийг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулаад, дахин хайх нь илүү үр дүнтэй."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Хайлтын явцад суваг олдсонгүй. USB тохируулагчийг залгасан бөгөөд ТВ дохионы үүсвэртэй холбосон эсэхээ шалгана уу.\n\nХэрэв агаарын антен хэрэглэж байгаа бол антены байршил эсвэл чиглэлийг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулахаад, дахин хайх нь илүү үр дүнтэй."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Хайлтын явцад суваг олдсонгүй. Сүлжээ тохируулагчийг асааж, ТВ дохионы үүсвэртэй холбосон эсэхээ шалгана уу.\n\nХэрэв агаарын антен хэрэглэж байгаа бол антены байршил, эсвэл чиглэлийг өөрчилнө үү. Антеныг өндөрт, цонхны дэргэд байрлуулаад, дахин хайна уу."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Дахин хайх"</item>
     <item msgid="2092797862490235174">"Дууссан"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"TВ-н суваг хайх"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"ТВ тохируулагчийн тохиргоо"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB ТВ тохируулагчийн тохиргоо"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB ТВ тохируулагч салсан байна."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TВ-н суваг хайх"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"ТВ тохируулагчийн тохиргоо"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB ТВ тохируулагчийн тохиргоо"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Сүлжээний ТВ тохируулагчийн тохиргоо"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB ТВ тохируулагч салсан байна."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Сүлжээ тааруулагч салсан байна."</string>
 </resources>
diff --git a/usbtuner-res/values-mr/strings.xml b/usbtuner-res/values-mr-rIN/strings.xml
similarity index 73%
rename from usbtuner-res/values-mr/strings.xml
rename to usbtuner-res/values-mr-rIN/strings.xml
index 2ea242f..3b8c901 100644
--- a/usbtuner-res/values-mr/strings.xml
+++ b/usbtuner-res/values-mr-rIN/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"टीव्ही ट्यूनर"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB टीव्ही ट्यूनर"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"चालू"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"बंद"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"नेटवर्क टीव्ही ट्यूनर (बीटा)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"कृपया प्रक्रिया पूर्ण होण्‍याची प्रतीक्षा करा"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"आपला चॅनेल स्रोत निवडा"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"सिग्नल नाही"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> वर ट्यून करण्‍यात अयशस्वी झाले"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ट्यून करण्यात अयशस्वी झाले"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ट्यूनर सॉफ्टवेअर अलीकडे अद्यतनित केले आहे. कृपया चॅनेल पुन्हा स्कॅन करा."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ऑडिओ सक्षम करण्यासाठी सिस्टीम ध्वनी सेटिंग्ज मध्ये सराउंड ध्वनी सक्षम करा"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"ऑडिओ प्ले करू शकत नाही. कृपया दुसरा टीव्ही वापरून पहा"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"चॅनेल ट्यूनर सेटअप"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"टीव्ही ट्यूनर सेटअप"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB चॅनेल ट्यूनर सेटअप"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"नेटवर्क ट्यूनर सेटअप"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"टीव्ही सिग्नल स्रोताशी आपला टीव्ही कनेक्ट केला असल्याची खात्री करा. \n\n बिनतारी अँटेना वापरत असल्‍यास, आपल्‍याला कदाचित सर्वाधिक चॅनेल मिळविण्‍यासाठी त्याचे स्थान किंवा दिशा समायोजित करावी लागेल. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB ट्यूनर प्लगिन केले आणि TV सिग्नल स्रोताशी कनेक्‍ट केले आहे हे सत्यापित करा.\n\nबिनतारी अँटेना वापरत असल्‍यास, आपल्‍याला कदाचित सर्वाधिक चॅनेल मिळविण्‍यासाठी त्याचे स्थान किंवा दिशा समायोजित करावी लागेल. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"नेटवर्क ट्यूनर प्लगिन केले आणि TV सिग्नल स्रोताशी कनेक्‍ट केले आहे हे सत्यापित करा.\n\nबिनतारी अँटेना वापरत असल्‍यास, आपल्‍याला कदाचित सर्वाधिक चॅनेल मिळविण्‍यासाठी त्याचे स्थान किंवा दिशा समायोजित करावी लागेल. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"सुरू ठेवा"</item>
     <item msgid="727245208787621142">"सध्या नाही"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"चॅनेल सेटअप वर परत यायचे?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"हे टीव्ही ट्यूनर वरून शोधलेले चॅनेल काढेल आणि नवीन चॅनेलसाठी पुन्हा स्कॅन करेल.\n\n टीव्ही सिग्नल स्रोताशी आपला टीव्ही कनेक्ट केला असल्याचे सत्यापित करा.\n\nबिनतारी अँटेना वापरत असल्‍यास, आपल्‍याला कदाचित सर्वाधिक चॅनेल मिळविण्‍यासाठी त्याचे स्थान किंवा दिशा समायोजित करावी लागेल. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"हे USB ट्यूनर वरून शोधलेले चॅनेल काढेल आणि नवीन चॅनेलसाठी पुन्हा स्कॅन करेल.\n\n USB ट्यूनर प्लगिन केले आणि TV सिग्नल स्त्रोताशी कनेक्‍ट केले आहे हे सत्यापित करा.\n\nबिनतारी अँटेना वापरत असल्‍यास, आपल्‍याला कदाचित सर्वाधिक चॅनेल मिळविण्‍यासाठी त्याचे स्थान किंवा दिशा समायोजित करावी लागेल. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"हे नेटवर्क ट्यूनर वरून शोधलेले चॅनेल काढेल आणि नवीन चॅनेलसाठी पुन्हा स्कॅन करेल.\n\n नेटवर्क ट्यूनर प्लगिन केले आणि टीव्ही सिग्नल स्रोताशी कनेक्‍ट केले आहे हे सत्यापित करा.\n\nबिनतारी अँटेना वापरत असल्‍यास, आपल्याला कदाचित सर्वाधिक चॅनेल मिळविण्‍यासाठी त्याचे स्थान किंवा दिशा समायोजित करावी लागेल. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"सुरू ठेवा"</item>
     <item msgid="235450158666155406">"रद्द करा"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"टीव्ही ट्यूनर सेटअप"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB चॅनेल ट्यूनर सेटअप"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"नेटवर्क चॅनेल ट्यूनर सेटअप"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"यास काही मिनिटे लागू शकतात"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ट्यूनर तात्पुरते उपलब्ध नाही किंवा रेकॉर्डिंगद्वारे आधीपासून वापरले गेले आहे."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"कोणतेही चॅनेल आढळले नाही"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"स्कॅन करताना कोणतेही चॅनेल आढळले नाही. टीव्ही सिग्नल स्रोताशी आपला टीव्ही कनेक्ट केला असल्याचे सत्यापित करा.\n\nबिनतारी अँटेना वापरत असल्‍यास, त्याचे स्थान किंवा दिशा समायोजित करा. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा आणि पुन्हा स्कॅन करा."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"स्कॅन करताना कोणतेही चॅनेल आढळले नाही. USB ट्यूनर प्लगिन केले आणि TV सिग्नल स्रोताशी कनेक्‍ट केले आहे हे सत्यापित करा.\n\nबिनतारी अँटेना वापरत असल्‍यास, त्याचे स्थान किंवा दिशा समायोजित करा. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा आणि पुन्हा स्कॅन करा."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"स्कॅन करताना कोणतेही चॅनेल आढळले नाहीत. नेटवर्क ट्यूनर प्लगिन केले आणि टीव्ही सिग्नल स्रोताशी कनेक्‍ट केले आहे हे सत्यापित करा.\n\nबिनतारी अँटेना वापरत असल्‍यास, त्याचे स्थान किंवा दिशा समायोजित करा. उत्कृष्‍ट परिणामांसाठी, त्‍यास उंचावर आणि खिडकी जवळ ठेवा आणि पुन्हा स्कॅन करा."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"पुन्हा स्कॅन करा"</item>
     <item msgid="2092797862490235174">"पूर्ण झाले"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"टीव्ही चॅनेलसाठी स्कॅन करा"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"टीव्ही ट्यूनर सेटअप"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB टीव्ही ट्यूनर सेटअप"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV ट्यूनर डिस्कनेक्ट केला."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"टीव्ही चॅनेलसाठी स्कॅन करा"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"टीव्ही ट्यूनर सेटअप"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB टीव्ही ट्यूनर सेटअप"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"नेटवर्क टीव्ही ट्यूनर सेटअप"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB टीव्ही ट्यूनर डिस्कनेक्ट केला."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"नेटवर्क ट्यूनर डिस्कनेक्ट केले."</string>
 </resources>
diff --git a/usbtuner-res/values-ms/strings.xml b/usbtuner-res/values-ms-rMY/strings.xml
similarity index 74%
rename from usbtuner-res/values-ms/strings.xml
rename to usbtuner-res/values-ms-rMY/strings.xml
index 578e8ae..c85ce14 100644
--- a/usbtuner-res/values-ms/strings.xml
+++ b/usbtuner-res/values-ms-rMY/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Penala TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Penala TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Hidupkan"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Matikan"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Penala TV Rangkaian (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Sila tunggu sehingga proses selesai"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Pilih sumber saluran anda"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Tiada Isyarat"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Gagal menala ke <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Gagal menala"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Perisian penala telah dikemas kini baru-baru ini. Sila imbas semula saluran."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Dayakan bunyi keliling dalam tetapan bunyi sistem untuk mendayakan audio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Tidak dapat memainkan audio. Sila cuba TV lain"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Persediaan penala saluran"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Persediaan Penala TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Persediaan penala saluran USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Persediaan penala rangkaian"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Sahkan bahawa TV anda disambungkan pada sumber isyarat TV.\n\nJika menggunakan antena siaran, anda mungkin perlu melaraskan peletakan atau arahnya untuk menerima saluran terbanyak. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Sahkan bahawa penala USB dipalamkan dan disambungkan pada sumber isyarat TV.\n\nJika menggunakan antena siaran, anda mungkin perlu melaraskan peletakan atau arahnya untuk menerima saluran terbanyak. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Sahkan bahawa penala rangkaian telah dihidupkan dan disambungkan pada sumber isyarat TV\n\nJika menggunakan antena siaran, anda mungkin perlu melaraskan peletakan atau arahnya untuk menerima saluran terbanyak. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Teruskan"</item>
     <item msgid="727245208787621142">"Bukan sekarang"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Jalankan semula persediaan saluran?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Tindakan ini akan mengalih keluar saluran yang ditemui daripada penala TV dan mengimbas saluran baharu sekali lagi.\n\nSahkan bahawa penala TV telah disambungkan pada sumber isyarat TV.\n\nJika menggunakan antena siaran, anda mungkin perlu melaraskan peletakan atau arahnya untuk menerima saluran terbanyak. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Tindakan ini akan mengalih keluar saluran yang ditemui daripada penala USB dan mengimbas saluran baharu sekali lagi.\n\nSahkan bahawa penala USB telah dipalamkan dan disambungkan pada sumber isyarat TV.\n\nJika menggunakan antena siaran, anda mungkin perlu melaraskan peletakan atau arahnya untuk menerima saluran terbanyak. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Tindakan ini akan mengalih keluar saluran yang ditemui daripada penala rangkaian dan mengimbas saluran baharu sekali lagi.\n\nSahkan bahawa penala rangkaian telah dihidupkan dan disambungkan pada sumber isyarat TV.\n\nJika menggunakan antena siaran, anda mungkin perlu melaraskan peletakan atau arahnya untuk menerima saluran terbanyak. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Teruskan"</item>
     <item msgid="235450158666155406">"Batal"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Persediaan penala TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Persediaan penala saluran USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Persediaan penala saluran rangkaian"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Proses ini mungkin mengambil masa beberapa minit"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Penala tidak tersedia buat sementara waktu atau sudah pun digunakan oleh rakaman."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Tiada Saluran ditemui"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Pengimbasan ini tidak menemui sebarang saluran. Sahkan bahawa TV anda disambungkan pada sumber isyarat TV.\n\nJika menggunakan antena siaran, laraskan peletakan atau arahnya. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap, kemudian imbas sekali lagi."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Pengimbasan tidak menemui sebarang saluran. Sahkan bahawa penala USB dipalamkan dan disambungkan pada sumber isyarat TV.\n\nJika menggunakan antena siaran, laraskan peletakan atau arahnya. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap, kemudian imbas sekali lagi."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Pengimbasan ini tidak menemui sebarang saluran. Sahkan bahawa penala rangkaian telah dihidupkan dan disambungkan pada sumber isyarat TV.\n\nJika menggunakan antena siaran, laraskan peletakan atau arahnya. Untuk mendapatkan hasil yang terbaik, letakkan antena itu di tempat yang tinggi dan berdekatan dengan tingkap, kemudian imbas sekali lagi."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Imbas lagi"</item>
     <item msgid="2092797862490235174">"Selesai"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Imbas saluran TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Persediaan Penala TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Persediaan Penala TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Penala TV USB diputuskan sambungan."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Imbas saluran TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Persediaan Penala TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Persediaan Penala TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Persediaan Penala TV Rangkaian"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Penala TV USB diputuskan sambungan."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Penala rangkaian diputuskan sambungan."</string>
 </resources>
diff --git a/usbtuner-res/values-my/strings.xml b/usbtuner-res/values-my-rMM/strings.xml
similarity index 74%
rename from usbtuner-res/values-my/strings.xml
rename to usbtuner-res/values-my-rMM/strings.xml
index 56a29e5..a2cf6c8 100644
--- a/usbtuner-res/values-my/strings.xml
+++ b/usbtuner-res/values-my-rMM/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"တီဗီချန်နယ်ချိန်ကိရိယာ"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB တီဗီချန်နယ်ချိန်ကိရိယာ"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"ဖွင့်ပါ"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"ပိတ်ပါ"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"ကွန်ရက်တီဗီ လိုင်းချိန်စနစ် (စမ်းသပ်ဆော့ဖ်ဝဲ)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"စီမံဆောင်ရွက်မှု အဆုံးသတ်ရန် ခဏစောင့်ပါ"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"သင့်ချန်နယ်လိုင်းထုတ်လွှင့်ရာ အရင်းအမြစ်ကို ရွေးပါ"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"လိုင်းမမိပါ"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> သို့ ချိန်ညှိခြင်း မအောင်မြင်ပါ"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ချိန်ညှိ၍ မရခဲ့ပါ"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ချန်နယ်ချိန်ဆော့ဖ်ဝဲကို မကြာသေးမီက အပ်ဒိတ်လုပ်ခဲ့သည်။ ချန်နယ်လိုင်းများကို ပြန်ရှာပါ။"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"အသံဖွင့်ရန် ပတ်ပတ်လည်အသံစနစ်ဆက်တင်များကို ဖွင့်ပါ"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"အသံဖွင့်၍မရပါ။ အခြားတီဗီတွင် စမ်းကြည့်ပါ"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"ချန်နယ်ချိန်ကိရိယာ ထည့်သွင်းတပ်ဆင်မှု"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"တီဗီချန်နယ်ချိန်ကိရိယာ ပြင်ဆင်သတ်မှတ်မှု"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB ချန်နယ်ချိန်ကိရိယာ ပြင်ဆင်သတ်မှတ်မှု"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"တီဗီလိုင်းဖမ်းကိရိယာ စနစ်ထည့်သွင်းမှု"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"သင့်တီဗီသည် တီဗီချန်နယ်ထုတ်လွှင့်ရာ အရင်းအမြစ်တစ်ခုနှင့် ချိတ်ဆက်ထားကြောင်း အတည်ပြုပါ။\n\nအကယ်၍ ကောင်းကင်အန်တန်နာတိုင်ကို အသုံးပြုနေပါက ချန်နယ်အများစုကို ဖမ်းယူနိုင်ရန် ၎င်း၏အနေအထား (သို့) ဦးတည်ဘက်ကို ချိန်ညှိရန် လိုပါသည်။ ရလဒ်များအကောင်းဆုံး ဖြစ်စေရန် ၎င်းကို ပြတင်းပေါက်နားတွင် မြင့်မြင့်ထားပါ။"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB ချန်နယ်ချိန်ကိရိယာကို တပ်ဆင်ထားပြီး တီဗီချန်နယ်ထုတ်လွှင့်ရာ အရင်းအမြစ်တစ်ခုနှင့် ချိတ်ဆက်ထားကြောင်း အတည်ပြုပါ။\n\nအကယ်၍ ကောင်းကင်အန်တန်နာတိုင်ကို အသုံးပြုနေပါက ချန်နယ်အများစုကို ဖမ်းယူနိုင်ရန် ၎င်း၏အနေအထား (သို့) ဦးတည်ဘက်ကို ချိန်ညှိရန် လိုပါသည်။ ရလဒ်များအကောင်းဆုံး ဖြစ်စေရန် ၎င်းကို ပြတင်းပေါက်နားတွင် မြင့်မြင့်ထားပါ။"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"တီဗီလိုင်းဖမ်းကိရိယာကို ပါဝါဖွင့်ထားခြင်း ရှိ မရှိနှင့် တီဗီစလောင်းသို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ။\n\nအင်တင်နာကို အသုံးပြုလျှင် ၎င်း၏အနေအထား သို့မဟုတ် ဦးတည်ချက်တို့ကို ချိန်ညှိရန် လိုအပ်ပါသည်။ အကောင်းဆုံးရလဒ်အတွက် ပြတင်းပေါက်အနီး အမြင့်ပိုင်းတွင် ထားပါ။"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"ရှေ့ဆက်ရန်"</item>
     <item msgid="727245208787621142">"မလုပ်သေးပါ"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"ချန်နယ်စနစ်ထည့်သွင်းမှု ပြန်စမလား။"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"ဤလုပ်ဆောင်ချက်သည် တီဗီချန်နယ်ချိန်ကိရိယာက တွေ့ရှိထားသော ချန်နယ်လိုင်းများကို ဖယ်ရှားလိုက်ပြီး ချန်နယ်အသစ်များကို ထပ်မံရှာဖွေလိမ့်မည်။\n\nသင့်တီဗီသည် တီဗီချန်နယ်ထုတ်လွှင့်ရာ အရင်းအမြစ်တစ်ခုနှင့် ချိတ်ဆက်ထားကြောင်း အတည်ပြုပါ။\n\nအကယ်၍ ကောင်းကင်အန်တန်နာတိုင်ကို အသုံးပြုနေပါက ချန်နယ်အများစုကို ဖမ်းယူနိုင်ရန် ၎င်း၏အနေအထား (သို့) ဦးတည်ဘက်ကို ချိန်ညှိရန် လိုပါသည်။ ရလဒ်များအကောင်းဆုံး ဖြစ်စေရန် ၎င်းကို ပြတင်းပေါက်နားတွင် မြင့်မြင့်ထားပါ။"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"ဤလုပ်ဆောင်ချက်သည် USB ချန်နယ်ချိန်ကိရိယာက တွေ့ရှိထားသော ချန်နယ်လိုင်းများကို ဖယ်ရှားလိုက်ပြီး ချန်နယ်အသစ်များကို ထပ်မံရှာဖွေလိမ့်မည်။\n\nUSB ချန်နယ်ချိန်ကိရိယာကို တပ်ဆင်ထားပြီး တီဗီချန်နယ်ထုတ်လွှင့်ရာ အရင်းအမြစ်တစ်ခုနှင့် ချိတ်ဆက်ထားကြောင်း အတည်ပြုပါ။\n\nအကယ်၍ ကောင်းကင်အန်တန်နာတိုင်ကို အသုံးပြုနေပါက ချန်နယ်အများစုကို ဖမ်းယူနိုင်ရန် ၎င်း၏အနေအထား (သို့) ဦးတည်ဘက်ကို ချိန်ညှိရန် လိုပါသည်။ ရလဒ်များအကောင်းဆုံး ဖြစ်စေရန် ၎င်းကို ပြတင်းပေါက်နားတွင် မြင့်မြင့်ထားပါ။"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"၎င်းသည် တီဗီလိုင်းဖမ်းကိရိယာက ရှာဖွေတွေ့ရှိခဲ့သည့် ချန်နယ်များကို ဖယ်ရှားလိုက်မည်ဖြစ်ပြီး ချန်နယ်အသစ်များကို ထပ်မံရှာဖွေသွားပါမည်။\n\nတီဗီလိုင်းဖမ်းကိရိယာကို ပါဝါဖွင့်ထားခြင်း ရှိ မရှိနှင့် တီဗီစလောင်းသို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ။\n\nအင်တင်နာကို အသုံးပြုလျှင် ၎င်း၏အနေအထား သို့မဟုတ် ဦးတည်ချက်တို့ကို ချိန်ညှိရန် လိုအပ်ပါသည်။ အကောင်းဆုံးရလဒ်အတွက် ပြတင်းပေါက်အနီး အမြင့်ပိုင်းတွင် ထားပါ။"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"ရှေ့ဆက်ရန်"</item>
     <item msgid="235450158666155406">"မလုပ်တော့"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"တီဗီချန်နယ်ချိန်ကိရိယာ ပြင်ဆင်သတ်မှတ်မှု"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB ချန်နယ်ချိန်ကိရိယာ ပြင်ဆင်သတ်မှတ်မှု"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"တီဗီလိုင်းဖမ်းကိရိယာ စနစ်ထည့်သွင်းမှု"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"မိနစ်အနည်းငယ် ကြာနိုင်ပါသည်"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"လိုင်းချိန်စက်သည် ယာယီမရနိုင်သေးပါ သို့မဟုတ် ဖမ်းယူခြင်းအတွက် အသုံးပြုနေပြီး ဖြစ်ပါသည်။"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"ချန်နယ်တစ်လိုင်းမျှ မတွေ့ပါ"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"ချန်နယ်များရှာဖွေရာတွင် တစ်လိုင်းမျှ ရှာမတွေ့ပါ။ သင့်တီဗီသည် တီဗီချန်နယ်ထုတ်လွှင့်ရာ အရင်းအမြစ်တစ်ခုနှင့် ချိတ်ဆက်ထားကြောင်း အတည်ပြုပါ။\n\n အကယ်၍ ကောင်းကင်အန်တန်နာတိုင်ကို အသုံးပြုနေပါက ၎င်း၏ အနေအထား (သို့) ဦးတည်ဘက်ကို ချိန်ညှိပါ။ ရလဒ်များအကောင်းဆုံးဖြစ်စေရန် ၎င်းကို ပြတင်းပေါက်နားတွင် မြင့်မြင့်ထားပြီး ထပ်ရှာကြည့်ပါ။"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"ချန်နယ်များရှာဖွေရာတွင် တစ်လိုင်းမျှ ရှာမတွေ့ပါ။ USB ချန်နယ်ချိန်ကိရိယာကို တပ်ဆင်ထား၍ တီဗီချန်နယ်ထုတ်လွှင့်ရာ အရင်းအမြစ်တစ်ခုနှင့် ချိတ်ဆက်ထားကြောင်း အတည်ပြုပါ။\n\n အကယ်၍ ကောင်းကင်အန်တန်နာတိုင်ကို အသုံးပြုနေပါက ၎င်း၏ အနေအထား (သို့) ဦးတည်ဘက်ကို ချိန်ညှိပါ။ ရလဒ်များအကောင်းဆုံးဖြစ်စေရန် ၎င်းကို ပြတင်းပေါက်နားတွင် မြင့်မြင့်ထားပြီး ထပ်ရှာကြည့်ပါ။"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"မည်သည့် ချန်နယ်မျှ ရှာမတွေ့ပါ။ တီဗီလိုင်းဖမ်းကိရိယာကို ပါဝါဖွင့်ထားခြင်းရှိ မရှိနှင့် တီဗီစလောင်းသို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ။\n\nအင်တင်နာကို အသုံးပြုလျှင် ၎င်း၏အနေအထား သို့မဟုတ် ဦးတည်ချက်တို့ကို ချိန်ညှိရန် လိုအပ်ပါသည်။ အကောင်းဆုံးရလဒ်အတွက် ပြတင်းပေါက်အနီး အမြင့်ပိုင်းတွင် ထားပါ။"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"ထပ်ရှာရန်"</item>
     <item msgid="2092797862490235174">"ပြီးသွားပြီ"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"တီဗီချန်နယ်များကို ရှာပါ"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"တီဗီချန်နယ်ချိန် ကိရိယာအက်ပ် ထည့်သွင်းမှု"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB တီဗီချန်နယ်ချိန်အက်ပ် ထည့်သွင်းမှု"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB တီဗီချိန်စက်ကို ဖြုတ်လိုက်ပါပြီ"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TV ချန်နယ်ရှာမည်"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"တီဗီဖမ်းစက် အပြင်အဆင်"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB တီဗီဖမ်းစက် အပြင်အဆင်"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"အင်တာနက် တီဗီဖမ်းစက် အပြင်အဆင်"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB တီဗီလိုင်းချိန်ကိရိယာကို ဖြုတ်လိုက်ပါပြီ။"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"ကွန်ရက်လိုင်းချိန်ကိရိယာကို ဖြုတ်လိုက်ပါပြီ။"</string>
 </resources>
diff --git a/usbtuner-res/values-nb/strings.xml b/usbtuner-res/values-nb/strings.xml
index bce9e17..ed45555 100644
--- a/usbtuner-res/values-nb/strings.xml
+++ b/usbtuner-res/values-nb/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV-tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-tuneren for TV"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"På"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Av"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Nettverkstuner for TV (betaversjon)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Vent til behandlingen er fullført"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Velg en kanalkilde"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Ikke noe signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Kunne ikke bytte kanal til <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Kunne ikke bytte kanal"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Programvaren for tuneren er nylig blitt oppdatert. Du må skanne kanalene på nytt."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Slå på surroundlyd i innstillingene for systemlyd for å slå på lyd"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Kan ikke spille av lyd. Prøv en annen TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Konfigurasjon av kanaler via tuneren"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Konfigurasjon av TV-tuneren"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Konfigurasjon av kanaler via USB-tuneren"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Konfigurasjon av nettverkstuner"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Bekreft at TV-en din er koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, kan det hende du må justere posisjonen eller retningen for å motta flest mulig kanaler. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Bekreft at USB-tuneren er plugget i og koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, kan det hende du må justere posisjonen eller retningen for å motta flest mulig kanaler. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Bekreft at nettverkstuneren er slått på og koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, må du kanskje justere posisjonen eller retningen for å motta flere kanaler. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Fortsett"</item>
     <item msgid="727245208787621142">"Ikke nå"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Vil du kjøre kanalkonfigureringen på nytt?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Dette fjerner kanalene som ble funnet med TV-tuneren, og skanner etter nye kanaler igjen.\n\nBekreft at TV-en din er koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, kan det hende du må justere posisjonen eller retningen for å motta flest mulig kanaler. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Dette fjerner kanaler som er funnet via USB-tuneren, og skanner på nytt etter nye kanaler.\n\nBekreft at USB-tuneren er plugget i og koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, kan det hende du må justere posisjonen eller retningen for å motta flest mulig kanaler. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Dette fjerner kanalene som ble funnet av nettverkstuneren, og skanner på nytt etter nye kanaler.\n\nBekreft at nettverkstuneren er slått på og koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, må du kanskje justere posisjonen eller retningen for å motta flere kanaler. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Fortsett"</item>
     <item msgid="235450158666155406">"Avbryt"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Konfigurasjon av TV-tuneren"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Konfigurasjon av kanaler via USB-tuneren"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Konfigurasjon av tuner for nettverkskanaler"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Dette kan ta flere minutter"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuneren er midlertidig utilgjengelig eller brukes allerede av opptak."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Fant ingen kanaler"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Ingen kanaler ble funnet under skanningen. Bekreft at TV-en din er koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, kan du justere posisjonen eller retningen. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu. Deretter skanner du på nytt."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Fant ingen kanaler under skanningen. Bekreft at USB-tuneren er plugget i og koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, kan du justere posisjonen eller retningen. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu. Deretter skanner du på nytt."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Skanningen fant ingen kanaler. Bekreft at nettverkstuneren er slått på og koblet til en TV-signalkilde.\n\nHvis du bruker en trådløs antenne, må du justere posisjonen eller retningen. For å få de beste resultatene bør du plassere antennen høyt og i nærheten av et vindu. Deretter skanner du på nytt."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Skann på nytt"</item>
     <item msgid="2092797862490235174">"Ferdig"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Skann etter TV-kanaler"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Konfigurasjon av TV-tuneren"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Konfigurasjon av USB-tuner for TV"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-tuneren for TV er frakoblet."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Skann etter TV-kanaler"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Konfigurasjon av TV-tuneren"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Konfigurasjon av USB-tuner for TV"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Konfigurasjon av nettverkstuner for TV"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-tuneren for TV er frakoblet."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Nettverkstuneren er frakoblet."</string>
 </resources>
diff --git a/usbtuner-res/values-ne/strings.xml b/usbtuner-res/values-ne-rNP/strings.xml
similarity index 72%
rename from usbtuner-res/values-ne/strings.xml
rename to usbtuner-res/values-ne-rNP/strings.xml
index 07d68e2..5f1e333 100644
--- a/usbtuner-res/values-ne/strings.xml
+++ b/usbtuner-res/values-ne-rNP/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV ट्युनर"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV ट्युनर"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"सक्रिय"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"निष्क्रिय"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"नेटवर्कको TV ट्युनर (बिटा)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"कृपया प्रक्रिया सम्पन्न हुने प्रतीक्षा गर्नुहोस्"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"आफ्नो च्यानलको स्रोत चयन गर्नुहोस्"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"कुनै सिग्‍नल छैन"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> मा ट्युन गर्न सकिएन"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ट्युन गर्न सकिएन"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ट्युनरको सफ्टवेयरलाई हालसालै अद्यावधिक गरिएको छ। कृपया च्यानलहरू पुन:स्क्यान गर्नुहोस्।"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"अडियोलाई सक्षम पार्न प्रणालीको ध्वनि सम्बन्धी सेटिङहरूमा गई सराउन्ड साउन्डलाई सक्षम पार्नुहोस्"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"अडियो बजाउन सकिँदैन। कृपया अर्को TV को प्रयोग गरी हेर्नुहोस्"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"च्यानल ट्युनरको सेटअप"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV ट्युनरको सेटअप"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB च्यानल ट्युनरको सेटअप"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"नेटवर्क ट्युनरको सेटअप"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"तपाईँको TV कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने धेरै च्यानलहरू प्राप्त गर्न तपाईँले त्यसको स्थान वा दिशा समायोजन गर्नुपर्ने हुन सक्छ। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राख्नुहोस्।"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB ट्युनर प्लगइन रहेको र कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने धेरै च्यानलहरू प्राप्त गर्न तपाईँले त्यसको स्थान वा दिशा समायोजन गर्नुपर्ने हुन सक्छ। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राख्नुहोस्।"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"नेटवर्क ट्युनर सक्रिय रहेको र कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने धेरै च्यानलहरू प्राप्त गर्न तपाईंले त्यसको स्थान वा दिशा समायोजन गर्नुपर्ने हुन सक्छ। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राख्नुहोस्।"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"जारी राख्नुहोस्"</item>
     <item msgid="727245208787621142">"अहिले होइन"</item>
@@ -40,12 +38,13 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"च्यानलको सेटअप पुनःसञ्चालन गर्ने हो?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"यसले USB ट्युनरबाट भेट्टिएका च्यानलहरूलाई हटाउनेछ र नयाँ च्यानलहरू भेट्टाउन फेरि स्क्यान गर्नेछ।\n\nतपाईँको TV कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने धेरै च्यानलहरू प्राप्त गर्न तपाईँले त्यसको स्थान वा दिशा समायोजन गर्नुपर्ने हुन सक्छ। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राख्नुहोस्।"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"यसले USB ट्युनरबाट भेट्टिएका च्यानलहरूलाई हटाउनेछ र नयाँ च्यानलहरू भेट्टाउन फेरि स्क्यान गर्नेछ।\n\nUSB ट्युनर प्लगइन गरिएको र कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने धेरै च्यानलहरू प्राप्त गर्न तपाईँले त्यसको स्थान वा दिशा समायोजन गर्नुपर्ने हुन सक्छ। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राख्नुहोस्।"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"यसले नेटवर्क ट्युनर मार्फत भेट्टिएका च्यानलहरूलाई हटाउनेछ र नयाँ च्यानलहरू भेट्टाउन फेरि स्क्यान गर्नेछ।\n\nनेटवर्क ट्युनरलाई सक्रिय गरिएको र कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने धेरै च्यानलहरू प्राप्त गर्न तपाईंले त्यसको स्थान वा दिशा समायोजन गर्नुपर्ने हुन सक्छ। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राख्नुहोस्।"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"जारी राख्नुहोस्"</item>
     <item msgid="235450158666155406">"रद्द गर्नुहोस्"</item>
   </string-array>
     <string name="ut_connection_title" msgid="8435949189164677545">"जडानको प्रकार चयन गर्नुहोस्"</string>
-    <string name="ut_connection_description" msgid="7234582943233286192">"यदि उक्त ट्युनरमा कुनै बाह्य एन्टेना जडान गरिएको छ भने एन्टेना छनौट गर्नुहोस्। यदि तपाईँका च्यानलहरू केबल सेवा प्रदायक मार्फत आउँछन् भने केबल छनौट गर्नुहोस्। यदि तपाईँ निश्चित हुनुहुन्न भने दुवै प्रकारहरू स्क्यान गरिने छन् तर यसमा लामो समय लाग्न सक्छ।"</string>
+    <string name="ut_connection_description" msgid="7234582943233286192">"यदि उक्त ट्युनरमा कुनै बाह्य एन्टेना जडान गरिएको छ भने एन्टेना छनौट गर्नुहोस्। यदि तपाईंका च्यानलहरू केबल सेवा प्रदायक मार्फत आउँछन् भने केबल छनौट गर्नुहोस्। यदि तपाईं निश्चित हुनुहुन्न भने दुवै प्रकारहरू स्क्यान गरिने छन् तर यसमा लामो समय लाग्न सक्छ।"</string>
   <string-array name="ut_connection_choices">
     <item msgid="1499878461856892555">"एन्टेना"</item>
     <item msgid="2670079958754180142">"केबल"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV ट्युनरको सेटअप"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB च्यानल ट्युनरको सेटअप"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"नेटवर्कको च्यानल ट्युनरको सेटअप"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"यसमा धेरै मिनेट लाग्न सक्छ"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ट्युनर अस्थायी रूपले अनुपलब्ध छ वा रेकर्डिङद्वारा पहिले नै प्रयोग गरिएको छ।"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"कुनै च्यानल भेट्टिएन"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"उक्त स्क्यानले कुनै पनि च्यानल भेट्टाएन। तपाईँको TV कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने त्यसको स्थान वा दिशा समायोजन गर्नुहोस्। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राखी फेरि स्क्यान गर्नुहोस्।"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"उक्त स्क्यानले कुनै पनि च्यानल भेट्टाएन। USB ट्युनर प्लगइन गरिएको र कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने त्यसको स्थान वा दिशा समायोजन गर्नुहोस्। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राखी फेरि स्क्यान गर्नुहोस्।"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"उक्त स्क्यानले कुनै पनि च्यानल भेट्टाएन। नेटवर्क ट्युनरलाई सक्रिय गरिएको र कुनै TV सिग्नलको स्रोतमा जडान गरिएको छ भनी पुष्टि गर्नुहोस्।\n\nयदि कुनै ओभर-दि-एयर एन्टेनाको प्रयोग भइरहेको छ भने त्यसको स्थान वा दिशा समायोजन गर्नुहोस्। उत्कृष्ट परिणामहरूका लागि त्यसलाई उच्च स्थानमा र कुनै झ्यालको नजिक राखी फेरि स्क्यान गर्नुहोस्।"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"फेरि स्क्यान गर्नुहोस्"</item>
     <item msgid="2092797862490235174">"सम्पन्न भयो"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"TV च्यानलहरू भेट्टाउन स्क्यान गर्नुहोस्"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV ट्युनरको सेटअप"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV ट्युनरको सेटअप"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV ट्युनरलाई विच्छेद गरियो।"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TV च्यानलहरू भेट्टाउन स्क्यान गर्नुहोस्"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV ट्युनरको सेटअप"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV ट्युनरको सेटअप"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"नेटवर्कको TV ट्युनरको सेटअप"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV ट्युनरलाई विच्छेद गरियो।"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"नेटवर्क ट्युनरलाई विच्छेद गरियो।"</string>
 </resources>
diff --git a/usbtuner-res/values-nl/strings.xml b/usbtuner-res/values-nl/strings.xml
index b9e1868..34b0d92 100644
--- a/usbtuner-res/values-nl/strings.xml
+++ b/usbtuner-res/values-nl/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Tv-tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-tv-tuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Aan"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Uit"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Netwerk-tv-tuner (BÈTA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Wacht tot het proces is voltooid"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Selecteer je kanaalbron"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Geen signaal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Kan niet afstemmen op <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Kan niet afstemmen"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"De software van de tuner is recent geüpdatet. Scan de kanalen opnieuw."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Schakel surrond sound in via de geluidsinstellingen van het systeem om audio in te schakelen"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Kan audio niet afspelen. Probeer een andere tv."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuratie van kanaaltuner"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Tv-tuner instellen"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Kanaalconfiguratie van USB-tuner"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Netwerktuner instellen"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Controleer of je tv is aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, moet je de positie of richting daarvan mogelijk aanpassen om zo veel mogelijk kanalen te ontvangen. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Controleer of de USB-tuner is ingeschakeld en aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, moet je de positie of richting daarvan mogelijk aanpassen om zo veel mogelijk kanalen te ontvangen. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Controleer of de netwerktuner is ingeschakeld en aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, moet je de positie of richting daarvan mogelijk aanpassen om zo veel mogelijk kanalen te ontvangen. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Doorgaan"</item>
     <item msgid="727245208787621142">"Niet nu"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Kanaalconfiguratie opnieuw uitvoeren?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Hiermee worden de gevonden kanalen verwijderd van de tv-tuner en wordt opnieuw gezocht naar nieuwe kanalen.\n\nControleer of je tv is aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, moet je de positie of richting daarvan mogelijk aanpassen om zo veel mogelijk kanalen te ontvangen. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Hiermee worden de gevonden kanalen verwijderd van de USB-tuner en wordt opnieuw gescand naar nieuwe kanalen.\n\nControleer of de USB-tuner is ingeschakeld en aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, moet je de positie of richting daarvan mogelijk aanpassen om zo veel mogelijk kanalen te ontvangen. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Hiermee worden de gevonden kanalen verwijderd van de netwerktuner en wordt opnieuw gezocht naar nieuwe kanalen.\n\nControleer of de netwerktuner is ingeschakeld en aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, moet je de positie of richting daarvan mogelijk aanpassen om zo veel mogelijk kanalen te ontvangen. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Doorgaan"</item>
     <item msgid="235450158666155406">"Annuleren"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Tv-tuner instellen"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Kanaalconfiguratie van USB-tuner"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Netwerkkanaaltuner instellen"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Dit kan enkele minuten duren"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"De tuner is tijdelijk niet beschikbaar of wordt al gebruikt voor een opname."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Geen kanalen gevonden"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Er zijn geen kanalen gevonden tijdens de scan. Controleer of je tv is aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, pas je de positie of richting daarvan aan. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam en voer je de scan opnieuw uit."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Er zijn geen kanalen gevonden tijdens de scan. Controleer of de USB-tuner is ingeschakeld en aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, pas je de positie of richting daarvan aan. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam en voer je de scan opnieuw uit."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"De scan heeft geen kanalen gevonden. Controleer of de netwerktuner is ingeschakeld en aangesloten op een tv-signaalbron.\n\nAls je een over-the-air-antenne gebruikt, moet je de positie of richting daarvan mogelijk aanpassen. Voor de beste resultaten plaats je de antenne op een hoge plek in de buurt van een raam en voer je de scan opnieuw uit."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Opnieuw scannen"</item>
     <item msgid="2092797862490235174">"Gereed"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Scannen naar tv-kanalen"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Tv-tuner instellen"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB-tv-tuner instellen"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-tv-tuner ontkoppeld."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Zoeken naar tv-zenders"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Tv-tuner instellen"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB-tv-tuner instellen"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Netwerk-tv-tuner instellen"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-tv-tuner losgekoppeld."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Netwerktuner losgekoppeld."</string>
 </resources>
diff --git a/usbtuner-res/values-pl/strings.xml b/usbtuner-res/values-pl/strings.xml
index 0bc7e73..9daa362 100644
--- a/usbtuner-res/values-pl/strings.xml
+++ b/usbtuner-res/values-pl/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Tuner TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Tuner TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Włącz"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Wyłącz"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Sieciowy tuner TV (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Poczekaj na zakończenie przetwarzania"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Wybierz źródło kanału"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Brak sygnału"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Nie udało się dostroić kanału <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Nie udało się dostroić kanału"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Oprogramowanie tunera zostało niedawno zaktualizowane. Przeskanuj ponownie kanały."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Aby włączyć dźwięk, włącz dźwięk przestrzenny w ustawieniach systemowych dźwięku"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Nie można odtworzyć dźwięku. Spróbuj użyć innego telewizora"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Konfiguracja kanałów w tunerze"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Konfiguracja tunera TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Konfiguracja kanałów w tunerze USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Konfiguracja tunera sieciowego"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Upewnij się, że telewizor jest podłączony do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, może być konieczne wyregulowanie jej położenia lub kierunku, by można było odbierać jak najwięcej kanałów. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Upewnij się, że tuner USB jest podłączony do telewizora oraz do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, może być konieczne wyregulowanie jej położenia lub kierunku, by można było odbierać jak najwięcej kanałów. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Upewnij się, że tuner sieciowy jest włączony i został podłączony do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, może być konieczne wyregulowanie jej położenia lub kierunku, by można było odbierać jak najwięcej kanałów. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Kontynuuj"</item>
     <item msgid="727245208787621142">"Nie teraz"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Skonfigurować ponownie kanały?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Spowoduje to usunięcie kanałów znalezionych przez tuner TV i ponowne wykonanie skanowania.\n\nUpewnij się, że telewizor jest podłączony do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, może być konieczne wyregulowanie jej położenia lub kierunku, by można było odbierać jak najwięcej kanałów. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Spowoduje to usunięcie kanałów znalezionych przez tuner USB i ponowne wykonanie skanowania.\n\nUpewnij się, że tuner USB jest podłączony do telewizora oraz do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, może być konieczne wyregulowanie jej położenia lub kierunku, by można było odbierać jak najwięcej kanałów. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Spowoduje to usunięcie kanałów znalezionych przez tuner sieciowy i ponowne wykonanie skanowania.\n\nUpewnij się, że tuner sieciowy jest włączony i został podłączony do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, może być konieczne wyregulowanie jej położenia lub kierunku, by można było odbierać jak najwięcej kanałów. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Kontynuuj"</item>
     <item msgid="235450158666155406">"Anuluj"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Konfiguracja tunera TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Konfiguracja kanałów w tunerze USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Konfiguracja kanałów w tunerze sieciowym"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Może to potrwać kilka minut"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuner jest czasowo niedostępny lub właśnie nagrywa."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -82,12 +82,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nie znaleziono kanałów"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Podczas skanowania nie znaleziono żadnych kanałów. Upewnij się, że telewizor jest podłączony do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, wyreguluj jej położenie lub kierunek. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna, a następnie ponownie wykonaj skanowanie."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Podczas skanowania nie znaleziono żadnych kanałów. Upewnij się, że tuner USB jest podłączony do telewizora oraz do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, wyreguluj jej położenie lub kierunek. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna, a następnie ponownie wykonaj skanowanie."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Podczas skanowania nie znaleziono żadnych kanałów. Upewnij się, że tuner sieciowy jest włączony i został podłączony do źródła sygnału telewizyjnego.\n\nJeśli używasz anteny telewizyjnej, wyreguluj jej położenie lub kierunek. Aby uzyskać najlepszy sygnał, umieść antenę na podwyższeniu, w pobliżu okna, a następnie ponownie wykonaj skanowanie."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Skanuj ponownie"</item>
     <item msgid="2092797862490235174">"Gotowe"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Wyszukaj kanały TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Konfiguracja tunera TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Konfiguracja tunera TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Tuner TV USB odłączony."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Wyszukaj kanały TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Konfiguracja tunera TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Konfiguracja tunera TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Konfiguracja sieciowego tunera TV"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Telewizyjny tuner USB rozłączony."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Tuner sieciowy rozłączony."</string>
 </resources>
diff --git a/usbtuner-res/values-pt-rPT/strings.xml b/usbtuner-res/values-pt-rPT/strings.xml
index c78c92c..02f4dd9 100644
--- a/usbtuner-res/values-pt-rPT/strings.xml
+++ b/usbtuner-res/values-pt-rPT/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sintonizador de TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Sintonizador de TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Ativar"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Desativar"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Sintonizador de televisão (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Aguarde enquanto o processamento é terminado"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Selecione a origem do canal"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Sem sinal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Falha ao sintonizar <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Falha ao sintonizar"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"O software do sintonizador foi atualizado recentemente. Procure novamente os canais."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Ative o som surround nas definições de som do sistema para ativar o áudio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Não é possível reproduzir áudio. Experimente outra TV."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuração do sintonizador de canais"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configuração do sintonizador de TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configuração do sintonizador de canais USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configuração do sintonizador de rede"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Confirme se a sua TV está ligada a uma fonte de sinal da TV.\n\nSe estiver a utilizar uma antena via rede sem fios, pode ter de ajustar a respetiva posição ou a direção para receber a maioria dos canais. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Confirme se o sintonizador USB está ativado e ligado a uma fonte de sinal da TV.\n\nSe estiver a utilizar uma antena via rede sem fios, pode ter de ajustar a respetiva posição ou a direção para receber a maioria dos canais. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Confirme se o sintonizador de rede está ligado à alimentação e ligado a uma fonte de sinal de TV.\n\nSe estiver a utilizar uma antena via rede sem fios, pode ter de ajustar a respetiva posição ou direção para receber a maioria dos canais. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continuar"</item>
     <item msgid="727245208787621142">"Agora não"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Pretende executar novamente a configuração do canal?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Esta ação remove os canais encontrados pelo sintonizador de TV e procura novamente canais novos.\n\nConfirme se a sua TV está ligada a uma fonte de sinal da TV.\n\nSe estiver a utilizar uma antena via rede sem fios, pode ter de ajustar a respetiva posição ou a direção para receber a maioria dos canais. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Esta ação remove os canais encontrados do sintonizador USB e procura novamente canais novos.\n\nConfirme se o sintonizador USB está ativado e ligado a uma fonte de sinal da TV.\n\nSe estiver a utilizar uma antena via rede sem fios, pode ter de ajustar a respetiva posição ou a direção para receber a maioria dos canais. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Esta ação vai remover os canais encontrados do sintonizador de rede e procurar novos canais novamente.\n\nConfirme se o sintonizador de rede está ligado à alimentação e ligado a uma fonte de sinal de TV.\n\nSe estiver a utilizar uma antena via rede sem fios, pode ter de ajustar a respetiva posição ou direção para receber a maioria dos canais. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continuar"</item>
     <item msgid="235450158666155406">"Cancelar"</item>
@@ -54,20 +53,21 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configuração do sintonizador de TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configuração do sintonizador de canais USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configuração do sintonizador de canais"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Esta operação pode demorar vários minutos"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"O sintonizador está temporariamente indisponível ou já está a ser utilizado pela gravação."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
-      <item quantity="other">%1$d canais encontrados</item>
       <item quantity="one">%1$d canal encontrado</item>
+      <item quantity="other">%1$d canais encontrados</item>
     </plurals>
     <string name="ut_stop_channel_scan" msgid="566811986747774193">"INTERROMPER A PROCURA DE CANAIS"</string>
     <plurals name="ut_result_found_title" formatted="false" msgid="1448908152026339099">
-      <item quantity="other">%1$d canais encontrados</item>
       <item quantity="one">%1$d canal encontrado</item>
+      <item quantity="other">%1$d canais encontrados</item>
     </plurals>
     <plurals name="ut_result_found_description" formatted="false" msgid="4132691388395648565">
+      <item quantity="one">Boa! Foi encontrado %1$d canal durante a procura de canais. Se isso não lhe parecer correto, experimente ajustar a posição da antena e procurar novamente.</item>
       <item quantity="other">Boa! Foram encontrados %1$d canais durante a procura de canais. Se isto não lhe parecer correto, experimente ajustar a posição da antena e procurar novamente.</item>
-      <item quantity="one">Boa! Foi encontrado %1$d canal durante a procura de canais. Se isto não lhe parecer correto, experimente ajustar a posição da antena e procurar novamente.</item>
     </plurals>
   <string-array name="ut_result_found_choices">
     <item msgid="3220617441427115421">"Concluído"</item>
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Não foram encontrados canais"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"A procura não encontrou quaisquer canais. Confirme se a TV está ligada a uma fonte de sinal da TV.\n\nSe estiver a utilizar uma antena via rede sem fios, ajuste a respetiva posição ou a direção. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela e procure novamente."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Não foram encontrados quaisquer canais. Verifique se o sintonizador USB está ativado e ligado a uma fonte de sinal da TV.\n\nSe estiver a utilizar uma antena via rede sem fios, ajuste a respetiva posição ou a direção. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela e procure novamente."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"A procura não encontrou quaisquer canais. Confirme se o sintonizador de rede está ligado à alimentação e ligado a uma fonte de sinal de TV.\n\nSe estiver a utilizar uma antena via rede sem fios, ajuste a respetiva posição ou direção. Para obter os melhores resultados, coloque-a num ponto alto e junto a uma janela. Em seguida, procure novamente."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Procurar novamente"</item>
     <item msgid="2092797862490235174">"Concluído"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Procurar canais de TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configuração do sintonizador de TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configuração do sintonizador de TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Sintonizador de TV USB desligado."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Procurar canais de TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configuração do sintonizador de TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configuração do sintonizador de TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configuração do sintonizador de TV por cabo"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Sintonizador de TV USB desligado."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Sintonizador de rede desligado."</string>
 </resources>
diff --git a/usbtuner-res/values-pt/strings.xml b/usbtuner-res/values-pt/strings.xml
index 3dfd30c..d123306 100644
--- a/usbtuner-res/values-pt/strings.xml
+++ b/usbtuner-res/values-pt/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sintonizador de TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Sintonizador de TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Ativar"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Desativar"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Sintonizador de rede de TV (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Aguarde a conclusão do processamento"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Selecione a fonte do canal"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Sem sinal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Falha ao sintonizar <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Falha ao sintonizar"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"O software do sintonizador foi atualizado recentemente. Procure os canais mais uma vez."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Ative o som surround nas configurações de som do sistema para ativar o áudio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Não foi possível reproduzir o áudio. Tente em outra TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configuração do sintonizador de canais"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configuração do Sintonizador de TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configuração do sintonizador de canais USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configuração do sintonizador de rede"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Verifique se sua TV está conecta a uma fonte de sinal de TV.\n\nSe você estiver usando uma antena Over-the-air (OTA), talvez seja necessário ajustar o posicionamento ou a direção dela para receber o máximo de canais. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Verifique se o sintonizador USB está conectado a uma fonte de sinal de TV.\n\nSe você usa uma antena Over the air, talvez seja necessário ajustar o posicionamento ou a direção dela para receber o maior número de canais. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Verifique se o sintonizador de rede está ligado e conectado a uma fonte de sinal de TV.\n\nSe você estiver usando uma antena OTA (over-the-air), talvez seja necessário ajustar o posicionamento ou a direção dela para receber o máximo de canais. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continuar"</item>
     <item msgid="727245208787621142">"Agora não"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Executar novamente a configuração de canais?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Isso removerá os canais encontrados do Sintonizador de TV e procurará novos canais mais uma vez.\n\nVerifique se sua TV está conectada a uma fonte de sinal de TV.\n\nSe você estiver usando uma antena Over-the-air (OTA), talvez seja necessário ajustar o posicionamento ou a direção dela para receber o máximo de canais. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Essa ação remove os canais encontrados pelo sintonizador USB e procura canais novamente.\n\nVerifique se o sintonizador USB está conectado a uma fonte de sinal de TV.\n\n.Se você usa uma antena Over the air, talvez seja necessário ajustar o posicionamento ou a direção dela para receber o maior número de canais. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Essa ação removerá os canais encontrados do sintonizador de rede e procurará novos canais mais uma vez.\n\nVerifique se o sintonizador de rede está ligado e conectado a uma fonte de sinal de TV.\n\nSe você estiver usando uma antena OTA (over-the-air), talvez seja necessário ajustar o posicionamento ou a direção dela para receber o máximo de canais. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continuar"</item>
     <item msgid="235450158666155406">"Cancelar"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configuração do Sintonizador de TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configuração do sintonizador de canais USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configuração do sintonizador de canais de rede"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Isso pode demorar alguns minutos"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"O sintonizador está temporariamente indisponível ou já está sendo usado pela gravação."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nenhum canal encontrado"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"A procura não encontrou nenhum canal. Verifique se sua TV está conectada a uma fonte de sinal de TV.\n\nSe você estiver usando uma antena Over-the-air (OTA), ajuste o posicionamento ou a direção dela. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela e procure novamente."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Nenhum canal foi encontrado pela procura. Verifique se o sintonizador USB está conectado a uma fonte de sinal de TV.\n\nSe você estiver usando uma antena Over the air, ajuste o posicionamento ou a direção dela. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela e procure novamente."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Nenhum canal foi encontrado pela procura. Verifique se o sintonizador de rede está ligado e conectado a uma fonte de sinal de TV.\n\nSe você estiver usando uma antena OTA (over-the-air), ajuste o posicionamento ou a direção dela. Para ter resultados melhores, coloque-a em um lugar alto e perto de uma janela, depois procure novamente."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Procurar novamente"</item>
     <item msgid="2092797862490235174">"Concluído"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Procurar canais de TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configuração do Sintonizador de TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configuração do Sintonizador de TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Sintonizador de TV USB desconectado."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Procurar canais de TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configuração do Sintonizador de TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configuração do Sintonizador de TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configuração do sintonizador de rede de TV"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Sintonizador de TV USB desconectado."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Sintonizador de rede desconectado."</string>
 </resources>
diff --git a/usbtuner-res/values-ro/strings.xml b/usbtuner-res/values-ro/strings.xml
index 57f1ca4..d30101a 100644
--- a/usbtuner-res/values-ro/strings.xml
+++ b/usbtuner-res/values-ro/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Tuner TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Tuner TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Activați"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Dezactivați"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Tuner de rețea TV (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Așteptați ca procesarea să fie finalizată"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Selectați sursa canalului"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Fără semnal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Canalul <xliff:g id="CHANNEL_NAME">%s</xliff:g> nu a putut fi selectat"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Canalul nu a putut fi selectat"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Software-ul tunerului a fost actualizat recent. Scanați din nou canalele."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Pentru a activa conținutul audio, activați sunetul surround din setările de sunet ale sistemului"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Conținutul audio nu poate fi redat. Încercați pe un alt televizor."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Configurarea tunerului de canale"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Configurarea tunerului TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Configurarea tunerului de canale USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Configurarea tunerului de rețea"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Asigurați-vă că televizorul este conectat la o sursă de semnal TV.\n\nDacă folosiți o antenă over the air, poate fi necesar să-i ajustați amplasarea sau direcția astfel încât să capteze majoritatea canalelor. Pentru cele mai bune rezultate, amplasați-o la înălțime și în apropierea unei ferestre."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Asigurați-vă că tunerul USB este conectat la o sursă de alimentare și la o sursă de semnal TV.\n\nDacă folosiți o antenă over the air, poate fi necesar să-i ajustați amplasarea sau direcția astfel încât să capteze majoritatea canalelor. Pentru cele mai bune rezultate, amplasați-o la înălțime și în apropierea unei ferestre."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Verificați dacă tunerul de rețea este pornit și conectat la o sursă de semnal TV.\n\nDacă folosiți o antenă over-the-air, ar putea fi necesar să-i ajustați poziția sau direcția pentru a recepționa cât mai multe canale. Pentru rezultate optime, plasați-o sus și lângă o fereastră."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Continuați"</item>
     <item msgid="727245208787621142">"Nu acum"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Configurați din nou canalul?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Astfel, vor fi eliminate canalele găsite de tunerul TV și se vor căuta din nou canale.\n\nAsigurați-vă că televizorul este conectat la o sursă de semnal TV.\n\nDacă folosiți o antenă over the air, poate fi necesar să-i ajustați amplasarea sau direcția astfel încât să capteze majoritatea canalelor. Pentru cele mai bune rezultate, amplasați-o la înălțime și în apropierea unei ferestre."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Astfel, vor fi eliminate canalele găsite de pe tunerul USB și se vor căuta din nou canale.\n\nAsigurați-vă că tunerul USB este conectat la o sursă de alimentare și la o sursă de semnal TV.\n\nDacă folosiți o antenă over the air, poate fi necesar să-i ajustați amplasarea sau direcția pentru a capta majoritatea canalelor. Pentru cele mai bune rezultate, amplasați-o la înălțime și în apropierea unei ferestre."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Astfel veți elimina canalele găsite din tunerul de rețea și veți scana iar pentru a găsi canale noi.\n\nVerificați dacă tunerul de rețea este pornit și conectat la o sursă de semnal TV.\n\nDacă folosiți o antenă over-the-air, ar putea fi necesar să-i ajustați poziția sau direcția pentru a recepționa cât mai multe canale. Pentru rezultate optime, plasați-o sus și lângă o fereastră."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Continuați"</item>
     <item msgid="235450158666155406">"Anulați"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Configurarea tunerului TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Configurarea tunerului de canale USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Configurarea tunerului de canale de rețea"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Poate dura câteva minute"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tunerul nu este disponibil temporar sau este folosit deja de înregistrare."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -79,12 +79,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nu s-au găsit canale"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Scanarea nu a găsit niciun canal. Asigurați-vă că televizorul este conectat la o sursă de semnal TV.\n\nDacă folosiți o antenă over the air, ajustați-i amplasarea sau direcția. Pentru cele mai bune rezultate, amplasați-o la înălțime și în apropierea unei ferestre, apoi repetați scanarea."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Nu s-a găsit niciun canal la scanare. Asigurați-vă că tunerul USB este conectat la o sursă de alimentare și la o sursă de semnal TV. \n\nDacă folosiți o antenă over the air, ajustați-i amplasarea sau direcția. Pentru cele mai bune rezultate, amplasați-o la înălțime și în apropierea unei ferestre, apoi repetați scanarea."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Scanarea nu a găsit niciun canal. Verificați dacă tunerul de rețea este pornit și conectat la o sursă de semnal TV.\n\nDacă folosiți o antenă over-the-air, ajustați poziția sau direcția. Pentru rezultate optime, plasați-o sus și lângă o fereastră și scanați din nou."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Scanați din nou"</item>
     <item msgid="2092797862490235174">"Terminat"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Căutați canale TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Configurarea tunerului TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Configurarea tunerului TV USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Tunerul TV USB a fost deconectat."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Căutați canale TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Configurarea tunerului TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Configurarea tunerului TV USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Configurarea tunerului de rețea TV"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Tunerul TV USB este deconectat."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Tunerul de rețea este deconectat."</string>
 </resources>
diff --git a/usbtuner-res/values-ru/strings.xml b/usbtuner-res/values-ru/strings.xml
index 7509ff1..33f97db 100644
--- a/usbtuner-res/values-ru/strings.xml
+++ b/usbtuner-res/values-ru/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ТВ-тюнер"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-тюнер"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Вкл."</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Выкл."</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Сетевой ТВ-тюнер (бета)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Дождитесь окончания обработки"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Выберите источник каналов"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Нет сигнала"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Не удалось настроиться на канал \"<xliff:g id="CHANNEL_NAME">%s</xliff:g>\""</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Не удалось настроиться на канал"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Программное обеспечение тюнера было обновлено. Повторите сканирование."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Включите объемный звук в системных настройках"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Не удается воспроизвести аудио. Выберите другой канал."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Настройка тюнера"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Настройка ТВ-тюнера"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Настройка USB-тюнера"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Настройка сетевого тюнера"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Убедитесь, что телевизор подключен к источнику сигнала.\n\nЕсли вы используете телеантенну, переместите или перенаправьте ее. Рекомендуем расположить ее высоко и рядом с окном."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Убедитесь, что USB-тюнер включен в сеть и подсоединен к источнику сигнала.\n\nЕсли вы используете телеантенну, переместите или перенаправьте ее. Рекомендуем расположить ее высоко и рядом с окном."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Убедитесь, что сетевой тюнер включен в сеть и подсоединен к источнику ТВ-сигнала.\n\nЕсли вы используете телеантенну, поместите и направьте ее так, чтобы она принимала большинство каналов. Рекомендуем расположить антенну высоко и рядом с окном."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Продолжить"</item>
     <item msgid="727245208787621142">"Не сейчас"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Настроить каналы заново?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Все каналы, найденные с помощью ТВ-тюнера, будут удалены, и поиск начнется заново.\n\nУбедитесь, что телевизор подключен к источнику сигнала.\n\nЕсли вы используете телеантенну, переместите или перенаправьте ее. Рекомендуем расположить ее высоко и рядом с окном."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Все каналы, найденные с помощью USB-тюнера, будут удалены, и сканирование начнется заново.\n\nУбедитесь, что USB-тюнер включен в сеть и подсоединен к источнику сигнала.\n\nЕсли вы используете телеантенну, переместите или перенаправьте ее. Рекомендуем расположить ее высоко и рядом с окном."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Все каналы, найденные с помощью сетевого тюнера, будут удалены, и сканирование начнется заново.\n\nУбедитесь, что сетевой тюнер включен в сеть и подсоединен к источнику ТВ-сигнала.\n\nЕсли вы используете телеантенну, поместите и направьте ее так, чтобы она принимала большинство каналов. Рекомендуем расположить антенну высоко и рядом с окном."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Продолжить"</item>
     <item msgid="235450158666155406">"Отмена"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Настройка ТВ-тюнера"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Настройка USB-тюнера"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Настройка каналов сетевого тюнера"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Это может занять несколько минут"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Тюнер временно недоступен или уже используется для записи."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -78,12 +78,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Каналы не найдены"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Каналы не найдены. Убедитесь, что телевизор подключен к источнику сигнала.\n\nЕсли вы используете телеантенну, переместите или перенаправьте ее. Рекомендуем расположить ее высоко и рядом с окном."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Каналы не найдены. Убедитесь, что USB-тюнер включен в сеть и подсоединен к источнику сигнала.\n\nЕсли вы используете телеантенну, переместите или перенаправьте ее. Рекомендуем расположить ее высоко и рядом с окном."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Каналы не найдены. Убедитесь, что сетевой тюнер включен в сеть и подсоединен к источнику ТВ-сигнала.\n\nЕсли вы используете телеантенну, переместите или перенаправьте ее (рекомендуем расположить антенну высоко и рядом с окном). Затем повторите сканирование."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Искать повторно"</item>
     <item msgid="2092797862490235174">"Готово"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Сканирование телеканалов"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Настройка ТВ-тюнера"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Настройка USB-тюнера"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-тюнер отключен."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Сканируйте телеканалы"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Настройка ТВ-тюнера"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Настройка USB-тюнера"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Настройка сетевого ТВ-тюнера"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-тюнер отключен."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Сетевой тюнер отключен."</string>
 </resources>
diff --git a/usbtuner-res/values-si/strings.xml b/usbtuner-res/values-si-rLK/strings.xml
similarity index 74%
rename from usbtuner-res/values-si/strings.xml
rename to usbtuner-res/values-si-rLK/strings.xml
index a792b2c..577015b 100644
--- a/usbtuner-res/values-si/strings.xml
+++ b/usbtuner-res/values-si-rLK/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV සුසරකය"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV සුසරකය"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"ක්‍රියාත්මක කරන්න"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"ක්‍රියාවිරහිත කරන්න"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"සැකසීම අවසන් කිරීමට කරුණාකර රැඳී සිටින්න"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"ඔබගේ නාලිකා මූලාශ්‍රය තෝරන්න"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"සංඥාවක් නැත"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> වෙත සුසර කිරීම අසාර්ථක විය"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"සුසර කිරීම අසාර්ථක විය"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"සුසරක මෘදුකාංගය පසුගියදා යාවත්කාලීන කර ඇත. කරුණාකර නාලිකා නැවත ස්කෑන් කරන්න."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ශ්‍රව්‍ය සබල කිරීමට හඬ සැකසීම් තුළ අවට හඬ සබල කරන්න"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"ශ්‍රව්‍යය ධාවනය කළ නොහැකිය. කරුණාකර වෙනත් TV එකක් උත්සාහ කරන්න"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"නාලිකා සුසරක පිහිටුවීම"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV සුසරක පිහිටුවීම"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB නාලිකා සුසරක පිහිටුවීම"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"ජාල සුසරකය පිහිටුවීම"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"ඔබේ TV, TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, ඔබට බොහොමයක් නාලිකා ලබා ගැනීමට පිහිටීම හෝ දිශාව සීරුමාරු කිරීමට අවශ්‍ය විය හැකිය. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබන්න."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"සුසරකය පේනුගත කර ඇති බව සහ TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, ඔබට බොහොමයක් නාලිකා ලබා ගැනීමට පිහිටීම හෝ දිශාව සීරුමාරු කිරීමට අවශ්‍ය විය හැකිය. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබන්න."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"ජාල සුසරකය බලයට සම්බන්ධ කර ඇති බව සහ TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, ඔබට බොහොමයක් නාලිකා ලබා ගැනීමට පිහිටීම හෝ දිශාව සීරුමාරු කිරීමට අවශ්‍ය විය හැකිය. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබන්න."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"දිගටම කර ගෙන යන්න"</item>
     <item msgid="727245208787621142">"දැන් නොවේ"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"නාලිකා පිහිටුවීම නැවත ධාවනය කරන්නද?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"මෙය TV සුසරකය වෙතින් සොයා ගත් නාලිකා ඉවත් කරනු ඇති අතර නව නාලිකා සඳහා නැවත ස්කෑන් කරනු ඇත.\n\nඔබේ TV, TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, ඔබට බොහොමයක් නාලිකා ලබා ගැනීමට පිහිටීම හෝ දිශාව සීරුමාරු කිරීමට අවශ්‍ය විය හැකිය. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබන්න."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"මෙය USB සුසරකය වෙතින් සොයා ගත් නාලිකා ඉවත් කරනු ඇති අතර නව නාලිකා සඳහා නැවත ස්කෑන් කරනු ඇත.\n\nUSB සුසරකය පේනුගත කර ඇති බව සහ TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, ඔබට බොහොමයක් නාලිකා ලබා ගැනීමට පිහිටීම හෝ දිශාව සීරුමාරු කිරීමට අවශ්‍ය විය හැකිය. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබන්න."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"මෙය ජාල සුසරකය වෙතින් සොයා ගත් නාලිකා ඉවත් කරනු ඇති අතර නව නාලිකා සඳහා නැවත ස්කෑන් කරනු ඇත.\n\nජාල සුසරකය බලයට සම්බන්ධ කර ඇති බව සහ TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, ඔබට බොහොමයක් නාලිකා ලබා ගැනීමට පිහිටීම හෝ දිශාව සීරුමාරු කිරීමට අවශ්‍ය විය හැකිය. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබන්න."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"දිගටම කර ගෙන යන්න"</item>
     <item msgid="235450158666155406">"අවලංගු කරන්න"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV සුසරක පිහිටුවීම"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB නාලිකා සුසරක පිහිටුවීම"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"ජාල නාලිකා සුසරකය පිහිටුවීම"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"මෙය මිනිත්තු කිහිපයක් ගත හැකිය"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"සුසරකය තාවකාලිකව ලබා ගත නොහැකිය නැතහොත් දැනටමත් පටිගත කිරීම මගින් භාවිත කරනු ලැබේ."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"නාලිකා හමු නොවීය"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"ස්කෑන් කිරීමට නාලිකා කිසිවක් හමු නොවීය. ඔබේ TV, TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, එහි පිහිටීම හෝ දිශාව සීරුමාරු කරන්න. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබා නැවත ස්කෑන් කරන්න."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"ස්කෑන් කිරීමට නාලිකා කිසිවක් හමු නොවීය. USB සුසරකය පේනුගත කර ඇති බව සහ TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, පිහිටීම හෝ දිශාව සීරුමාරු කරන්න. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබා නැවත ස්කෑන් කරන්න."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"ස්කෑන් කිරීමට නාලිකා කිසිවක් හමු නොවීය. ජාල සුසරකය බලයට සම්බන්ධ කර ඇති බව සහ TV සංඥා මූලාශ්‍රයකට සම්බන්ධ කර ඇති බව තහවුරු කර ගන්න.\n\nගුවන-ඔස්සේ ඇන්ටනාවක් භාවිත කරන්නේ නම්, පිහිටීම හෝ දිශාව සීරුමාරු කරන්න. හොඳම ප්‍රතිඵල සඳහා, එය ඉහළින් සහ කවුළුවක් ආසන්නයේ තබා නැවත ස්කෑන් කරන්න."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"නැවත ස්කෑන් කරන්න"</item>
     <item msgid="2092797862490235174">"නිමයි"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"TV නාලිකා සඳහා ස්කෑන් කරන්න"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV සුසරක පිහිටුවීම"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV සුසරක පිහිටුවීම"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV සුසරකය විසන්ධි කරන ලදී."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TV නාලිකා සඳහා ස්කෑන් කරන්න"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV සුසරක පිහිටුවීම"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV සුසරක පිහිටුවීම"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"ජාල TV සුසරක පිහිටුවීම"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV සුසරකය විසන්ධි වුණි."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"ජාල සුසරකය විසන්ධි වුණි."</string>
 </resources>
diff --git a/usbtuner-res/values-sk/strings.xml b/usbtuner-res/values-sk/strings.xml
index 67f9829..60448b2 100644
--- a/usbtuner-res/values-sk/strings.xml
+++ b/usbtuner-res/values-sk/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Televízny tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Televízny tuner s rozhraním USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Zapnúť"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Vypnúť"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Televízny sieťový tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Počkajte, kým bude spracovanie dokončené"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Vyberte zdroj kanála"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Žiadny signál"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Nepodarilo sa naladiť kanál <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Ladenie zlyhalo"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Softvér tunera bol nedávno aktualizovaný. Znova vyhľadajte kanály."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Ak chcete zapnúť zvuk, v nastaveniach systémového zvuku povoľte priestorový zvuk"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Zvuk nie je možné prehrať. Skúste použiť iný televízor."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Nastavenie tunera kanálov"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Nastavenie televízneho tunera"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Nastavenie kanálov tunera USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Nastavenie sieťového tunera"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Skontrolujte, či je televízor pripojený k zdroju televízneho signálu.\n\nAk používate vzdušnú anténu, upravte jej umiestnenie alebo orientáciu, aby ste získali čo najviac kanálov. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Skontrolujte, či je tuner USB zapojený a pripojený k zdroju televízneho signálu.\n\nAk používate vzdušnú anténu, upravte jej umiestnenie alebo orientáciu, aby ste získali čo najviac kanálov. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Skontrolujte, či je sieťový tuner zapnutý a pripojený k zdroju televízneho signálu.\n\nAk používate bezdrôtovú anténu, upravte jej umiestnenie alebo orientáciu tak, aby ste získali čo najviac kanálov. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Pokračovať"</item>
     <item msgid="727245208787621142">"Teraz nie"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Znova spustiť nastavenie kanálov?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Táto akcia odstráni nájdené kanály z televízneho tunera a opätovne spustí vyhľadávanie nových kanálov.\n\nSkontrolujte, či je televízor pripojený k zdroju televízneho signálu.\n\nAk používate vzdušnú anténu, upravte jej umiestnenie alebo orientáciu, aby ste získali čo najviac kanálov. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Táto akcia odstráni nájdené kanály z tunera USB a opätovne spustí vyhľadávanie nových kanálov.\n\nSkontrolujte, či je tuner USB zapojený a pripojený k zdroju televízneho signálu.\n\nAk používate vzdušnú anténu, upravte jej umiestnenie alebo orientáciu, aby ste získali čo najviac kanálov. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Táto akcia odstráni nájdené kanály zo sieťového tunera a opätovne spustí vyhľadávanie nových kanálov.\n\nSkontrolujte, či je sieťový tuner zapnutý a pripojený k zdroju televízneho signálu.\n\nAk používate bezdrôtovú anténu, upravte jej umiestnenie alebo orientáciu tak, aby ste získali čo najviac kanálov. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Pokračovať"</item>
     <item msgid="235450158666155406">"Zrušiť"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Nastavenie televízneho tunera"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Nastavenie kanálov tunera USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Nastavenie kanálov sieťového tunera"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Môže to trvať niekoľko minút"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tuner nie je dočasne kˆ dispozícii alebo sa práve používa na nahrávanie."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -82,12 +82,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Nenašli sa žiadne kanály"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Nenašli sa žiadne kanály. Skontrolujte, či je televízor pripojený k zdroju televízneho signálu.\n\nAk používate vzdušnú anténu, upravte jej umiestnenie alebo orientáciu. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna. Potom znova spustite hľadanie."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Nenašli sa žiadne kanály. Skontrolujte, či je tuner USB zapojený a pripojený k zdroju televízneho signálu.\n\nAk používate vzdušnú anténu, upravte jej umiestnenie alebo orientáciu. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna. Potom znova spustite hľadanie."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Nenašli sa žiadne kanály. Skontrolujte, či je sieťový tuner zapnutý a pripojený k zdroju televízneho signálu.\n\nAk používate bezdrôtovú anténu, upravte jej umiestnenie alebo orientáciu. Najlepšie výsledky dosiahnete umiestnením antény dostatočne vysoko a do blízkosti okna. Potom znova spustite hľadanie."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Hľadať znova"</item>
     <item msgid="2092797862490235174">"Hotovo"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Vyhľadajte televízne kanály"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Nastavenie televízneho tunera"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Nastavenie televízneho tunera s rozhraním USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"TV tuner s rozhraním USB je odpojený."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Vyhľadajte televízne kanály"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Nastavenie televízneho tunera"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Nastavenie televízneho tunera s rozhraním USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Nastavenie televízneho sieťového tunera"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"TV tuner s rozhraním USB bol odpojený."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Sieťový tuner bol odpojený."</string>
 </resources>
diff --git a/usbtuner-res/values-sl/strings.xml b/usbtuner-res/values-sl/strings.xml
index e454e97..2f0812b 100644
--- a/usbtuner-res/values-sl/strings.xml
+++ b/usbtuner-res/values-sl/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Sprejemnik TV-kanalov"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Sprejemnik TV-kanalov USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Vklop"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Izklop"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Omrežni sprejemnik TV-kanalov (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Počakajte, da se dokonča obdelava"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Izberite vir kanalov"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Ni signala"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Iskanje kanala <xliff:g id="CHANNEL_NAME">%s</xliff:g> ni uspelo"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Iskanje kanala ni uspelo"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Programska oprema sprejemnika je bila nedavno posodobljena. Znova poiščite kanale."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"V sistemskih nastavitvah zvoka omogočite prostorski zvok, če želite omogočiti zvok"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Zvoka ni mogoče predvajati. Poskusite na drugem televizorju."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Nastavitev sprejemnika kanalov"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Nastavitev sprejemnika TV-kanalov"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Nastavitev sprejemnika kanalov USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Nastavitev omrežnega sprejemnika"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Preverite, ali je televizor povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, prilagodite njen položaj oziroma njeno usmerjenost. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna ter iščite kanale znova."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Preverite, ali je sprejemnik USB priključen in povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, morate morda prilagoditi njen položaj oziroma njeno usmerjenost, če želite prejemati največ kanalov. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Preverite, ali je omrežni sprejemnik vklopljen in povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, prilagodite njen položaj oziroma njeno usmerjenost. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Naprej"</item>
     <item msgid="727245208787621142">"Ne zdaj"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Ali želite znova zagnati namestitev kanalov?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"S tem bodo odstranjeni kanali, najdeni prek sprejemnika TV-kanalov, in iskanje kanalov se bo začelo znova.\n\nPreverite, ali je televizor povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, prilagodite njen položaj oziroma njeno usmerjenost. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna ter iščite kanale znova."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"S tem bodo odstranjeni kanali, najdeni prek sprejemnika USB, in iskanje kanalov se bo začelo znova.\n\nPreverite, ali je sprejemnik USB priključen in povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, morate morda prilagoditi njen položaj oziroma njeno usmerjenost, če želite prejemati največ kanalov. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"S tem bodo odstranjeni kanali, najdeni z omrežnim sprejemnikom kanalov, in vnovič se bo začelo iskanje novih kanalov.\n\nPreverite, ali je omrežni sprejemnik vklopljen in povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, prilagodite njen položaj oziroma njeno usmerjenost. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Naprej"</item>
     <item msgid="235450158666155406">"Prekliči"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Nastavitev sprejemnika TV-kanalov"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Nastavitev sprejemnika kanalov USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Nastavitev omrežnega sprejemnika kanalov"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"To lahko traja nekaj minut"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Sprejemnik začasno ni na voljo ali se že uporablja za snemanje."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -82,12 +82,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Ni najdenih kanalov"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Pri iskanju kanali niso bili najdeni. Preverite, ali je televizor povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, prilagodite njen položaj oziroma njeno usmerjenost. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna ter iščite kanale znova."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Pri iskanju kanali niso bili najdeni. Preverite, ali je sprejemnik USB priključen in povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, prilagodite njen položaj oziroma njeno usmerjenost. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna ter iščite kanale znova."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Pri iskanju ni bil najden noben kanal. Preverite, ali je omrežni sprejemnik vklopljen in povezan z virom TV-signala.\n\nČe uporabljate anteno za prizemno televizijo, prilagodite njen položaj oziroma njeno usmerjenost. Če želite najboljši rezultat, jo postavite na visok položaj in blizu okna ter iščite kanale znova."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Znova išči"</item>
     <item msgid="2092797862490235174">"Končano"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Iskanje TV-kanalov"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Nastavitev sprejemnika TV-kanalov"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Nastavitev sprejemnika TV-kanalov USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Povezava s sprejemnikom za TV-kanale USB je prekinjena."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Iskanje TV-kanalov"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Nastavitev sprejemnika TV-kanalov"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Nastavitev sprejemnika TV-kanalov USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Nastavitev omrežnega sprejemnika TV-kanalov"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Povezava s sprejemnikom za TV-kanale USB je prekinjena."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Povezava z omrežnim sprejemnikom je prekinjena."</string>
 </resources>
diff --git a/usbtuner-res/values-sr/strings.xml b/usbtuner-res/values-sr/strings.xml
index 6c1fa1b..ce7c4d5 100644
--- a/usbtuner-res/values-sr/strings.xml
+++ b/usbtuner-res/values-sr/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Тјунер за ТВ"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB тјунер за ТВ"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Укључи"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Искључи"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Мрежни тјунер за ТВ (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Сачекајте да се заврши обрада"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Изаберите извор канала"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Нема сигнала"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Укључивање канала <xliff:g id="CHANNEL_NAME">%s</xliff:g> није успело"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Укључивање канала није успело"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Софтвер тјунера је недавно ажуриран. Претражите канале поново."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Омогући звучни систем у подешавањима звука да бисте омогућили аудио"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Звук не може да се пусти. Испробајте други ТВ уређај"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Подешавање тјунера за канале"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Подешавање тјунера за ТВ"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Подешавање USB тјунера за канале"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Подешавање мрежног тјунера"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Проверите да ли је ТВ повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, можда треба да прилагодите њен положај или смер да бисте имали највише канала. Ако желите најбоље резултате, поставите је високо и близу прозора."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Проверите да ли је USB тјунер прикључен и повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, можда треба да прилагодите њен положај или смер да бисте имали највише канала. Ако желите најбоље резултате, поставите је високо и близу прозора."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Проверите да ли је мрежни тјунер укључен и повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, можда треба да прилагодите њен положај или смер да бисте имали највише канала. Ако желите најбоље резултате, поставите је високо и близу прозора."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Настави"</item>
     <item msgid="727245208787621142">"Не сада"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Желите ли да поново покренете подешавање канала?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"На овај начин уклањате канале пронађене помоћу тјунера за ТВ и поново тражите нове канале.\n\nПроверите да ли је ТВ повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, можда треба да прилагодите њен положај или смер да бисте имали највише канала. Ако желите најбоље резултате, поставите је високо и близу прозора."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"На овај начин уклањате канале пронађене помоћу USB тјунера и поново тражите нове канале.\n\nПроверите да ли је USB тјунер прикључен и повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, можда треба да прилагодите њен положај или смер да бисте имали највише канала. Ако желите најбоље резултате, поставите је високо и близу прозора."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"На овај начин уклањате канале пронађене помоћу мрежног тјунера и поново скенирате нове канале.\n\nПроверите да ли је мрежни тјунер укључен и повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, можда треба да прилагодите њен положај или смер да бисте имали највише канала. Ако желите најбоље резултате, поставите је високо и близу прозора."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Настави"</item>
     <item msgid="235450158666155406">"Откажи"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Подешавање тјунера за ТВ"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Подешавање USB тјунера за канале"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Подешавање мрежног тјунера за канале"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Ово може да потраје неколико минута"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Тјунер привремено није доступан или се већ користи за снимање."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -79,12 +79,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Није пронађен ниједан канал"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Претрагом није пронађен ниједан канал. Проверите да ли је ТВ повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, прилагодите њен положај или смер. Ако желите најбоље резултате, поставите је високо и близу прозора, па поново обавите претрагу."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Претрагом није пронађен ниједан канал. Проверите да ли је USB тјунер прикључен и повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, прилагодите њен положај или смер. Ако желите најбоље резултате, поставите је високо и близу прозора, па поново обавите претрагу."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Скенирањем није пронађен ниједан канал. Проверите да ли је мрежни тјунер укључен и повезан са извором ТВ сигнала.\n\nАко користите антену за сигнал преко мреже, прилагодите њен положај или смер. Ако желите најбоље резултате, поставите је високо и близу прозора, па поново обавите скенирање."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Претражи поново"</item>
     <item msgid="2092797862490235174">"Готово"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Потражите ТВ канале"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Подешавање тјунера за ТВ"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Подешавање USB тјунера за ТВ"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB тјунер за ТВ није прикључен."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Потражите ТВ канале"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Подешавање тјунера за ТВ"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Подешавање USB тјунера за ТВ"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Подешавање мрежног тјунера за ТВ"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB тјунер за ТВ није прикључен."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Мрежни тјунер није прикључен."</string>
 </resources>
diff --git a/usbtuner-res/values-sv/strings.xml b/usbtuner-res/values-sv/strings.xml
index dea421b..81c3792 100644
--- a/usbtuner-res/values-sv/strings.xml
+++ b/usbtuner-res/values-sv/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV-mottagare"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB-TV-mottagare"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"På"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Av"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Mottagare för TV över nätverket (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Vänta tills sökningen är klar"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Välj kanalkälla"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Ingen signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Det gick inte att ställa in <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Det gick inte att ställa in kanalen"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Programvaran för mottagaren har nyligen uppdaterats. Sök igenom kanalerna igen."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Aktivera surroundljud under inställningarna för systemljud om du vill aktivera ljud"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Det går inte att spela upp ljud. Testa en annan TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Inställning av kanalmottagare"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Konfiguration av TV-mottagare"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Kanalinställning för USB-mottagare"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Konfiguration av nätverksmottagare"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Verifiera att TV:n är ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar justerar du dess placering eller riktning. Placera den högt upp och nära ett fönster och sök på nytt för bästa resultat."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Verifiera att USB-mottagaren är ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar kan du behöva justera dess placering eller riktning för att hitta så många kanaler som möjligt. Placera den högt upp och nära ett fönster för bästa resultat."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Verifiera att nätverksmottagaren är på och ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar justerar du dess placering eller riktning. Placera den högt upp och nära ett fönster och sök på nytt för bästa resultat."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Fortsätt"</item>
     <item msgid="727245208787621142">"Inte nu"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Vill du göra om kanalinställningen?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Kanalerna som hittats via TV-mottagaren tas bort och en ny kanalsökning startas.\n\nVerifiera att TV:n är ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar justerar du dess placering eller riktning. Placera den högt upp och nära ett fönster och sök på nytt för bästa resultat."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Kanalerna som hittats via USB-mottagaren tas bort och en ny kanalsökning startas.\n\nVerifiera att USB-mottagaren är ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar kan du behöva justera dess placering eller riktning för att hitta så många kanaler som möjligt. Placera den högt upp och nära ett fönster för bästa resultat."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Åtgärden tar bort alla kanaler som hittades av nätverksmottagaren och söker efter nya kanaler igen.\n\nVerifiera att nätverksmottagaren är på och ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar justerar du dess placering eller riktning. Placera den högt upp och nära ett fönster och sök på nytt för bästa resultat."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Fortsätt"</item>
     <item msgid="235450158666155406">"Avbryt"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Konfiguration av TV-mottagare"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Kanalinställning för USB-mottagare"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Konfiguration av mottagare för nätverkskanaler"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Det här kan ta flera minuter"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Mottagaren är inte tillgänglig just nu eller så spelas andra program in med den."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Inga kanaler hittades"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Inga kanaler hittades vid sökningen. Verifiera att TV:n är ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar justerar du dess placering eller riktning. Placera den högt upp och nära ett fönster och sök på nytt för bästa resultat."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Inga kanaler hittades vid sökningen. Verifiera att USB-mottagaren är ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar justerar du dess placering eller riktning. Placera den högt upp och nära ett fönster och sök på nytt för bästa resultat."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Inga kanaler hittades under genomsökningen. Verifiera att nätverksmottagaren är på och ansluten till en signalkälla på TV:n.\n\nOm du använder en antenn för over the air-uppdateringar justerar du dess placering eller riktning. Placera den högt upp och nära ett fönster och sök på nytt för bästa resultat."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Sök igen"</item>
     <item msgid="2092797862490235174">"Klar"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Sök efter TV-kanaler"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Konfiguration av TV-mottagare"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Konfiguration av USB-TV-mottagare"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-TV-mottagaren har kopplats från"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Sök efter TV-kanaler"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Konfiguration av TV-mottagare"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Konfiguration av USB-ansluten TV-mottagare"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Konfiguration av nätverksansluten TV-mottagare"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-TV-mottagaren har kopplats från."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Nätverksmottagaren har kopplats från."</string>
 </resources>
diff --git a/usbtuner-res/values-sw/strings.xml b/usbtuner-res/values-sw/strings.xml
index 1ade751..c81614c 100644
--- a/usbtuner-res/values-sw/strings.xml
+++ b/usbtuner-res/values-sw/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Kitafutaji cha vituo vya TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Kitafutaji cha Vituo vya TV cha USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Washa"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Zima"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Kitafuta Vituo vya TV ya Mtandao (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Tafadhali subiri ili shughuli imalizike"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Chagua chanzo cha kituo"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Hakuna Mawimbi"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Imeshindwa kupata kituo cha <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Imeshindwa kupata kituo"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Programu ya kitafutaji cha vituo cha USB ilisasishwa hivi majuzi. Tafadhali tafuta vituo tena."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Washa sauti ya mzunguko katika mipangilio ya mfumo wa sauti ili uruhusu sauti"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Haiwezi kucheza sauti. Tafadhali jaribu TV nyingine"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kuweka mipangilio ya kitafutaji cha vituo"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Kuweka mipangilio ya kitafutaji cha vituo vya TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Kuweka mipangilio ya kitafutaji cha vituo cha USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Kuweka mipangilio ya kitafuta vituo vya TV"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Hakikisha TV yako imeunganishwa kwenye chanzo cha TV.\n\nIkiwa unatumia antena ya hewani, rekebisha jinsi ilivyowekwa au mwelekeo wake. Ili kupata matokeo bora zaidi, ipandishe juu na uiweke karibu na dirisha."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Thibitisha kuwa kitafutaji cha vituo cha USB kimechomekwa katika chanzo cha umeme na kuunganishwa katika chanzo cha mawimbi ya TV.\n\nKama unatumia antena ya hewani, rekebisha mkao wake au kule inakoelekea. Kwa matokeo bora zaidi, iweke juu , karibu na dirisha."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Thibitisha kuwa kitafuta vituo kimewashwa na kuunganishwa kwenye chanzo cha mawimbi ya TV. \n\nIkiwa unatumia antena ya hewani, huenda ukahitaji kurekebisha jinsi ilivyowekwa au inakoelekea, ili upate vituo vingi. Kwa matokeo bora zaidi, ipandishe juu na iwe karibu na dirisha."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Endelea"</item>
     <item msgid="727245208787621142">"Si sasa"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Ungependa kuweka mipangilio ya vituo upya?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Hatua hii itaondoa vituo vilivyopatikana kwenye kitafutaji cha vituo vya TV na kutafuta vituo vipya tena.\n\nHakikisha TV yako imeunganishwa kwenye chanzo cha mawimbi ya TV.\n\nIkiwa unatumia antena ya hewani, rekebisha jinsi ilivyowekwa au mwelekeo wake. Ili kupata matokeo bora zaidi, ipandishe juu na uiweke karibu na dirisha kisha utafute tena."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Hatua hii itaondoa vituo vilivyopatikana kwenye kitafutaji cha vituo cha USB na kutafuta vituo tena. \n\nThibitisha kuwa kitafutaji cha vituo cha USB kimechomekwa kwenye chanzo cha umeme na kuunganishwa katika chanzo cha mawimbi ya TV.\n\nKama unatumia antena ya hewani, rekebisha mkao wake au kule inakoelekea. Kwa matokeo bora zaidi, iweke juu, karibu na dirisha."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Hatua hii itaondoa vituo ulivyopata kwenye kitafuta vituo na kutafuta vituo vipya tena.\n\nThibitisha kwamba kitafuta vituo kimewashwa na kuunganishwa kwenye chanzo cha mawimbi ya TV.\n\nIkiwa unatumia antena ya hewani, rekebisha jinsi ilivyowekwa au inakoelekea, ili upate vituo vingi. Kwa matokeo bora zaidi, ipandishe juu na iwe karibu na dirisha."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Endelea"</item>
     <item msgid="235450158666155406">"Ghairi"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Kuweka mipangilio ya kitafutaji cha vituo vya TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Kuweka mipangilio ya kitafutaji cha vituo cha USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Kuweka mipangilio ya kitafuta vituo"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Shughuli hii inaweza kuchukua dakika kadhaa"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Kitafuta vituo hakipatikani kwa sasa au tayari kinatumiwa kurekodi."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Hakuna Vituo vilivyopatikana"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Hakuna vituo vilivyopatikana baada ya kutafuta. Hakikisha TV yako imeunganishwa kwenye chanzo cha mawimbi ya TV.\n\nIkiwa unatumia antena ya hewani, rekebisha jinsi ilivyowekwa au mwelekeo wake. Ili kupata matokeo bora zaidi, ipandishe juu na uiweke karibu na dirisha kisha utafute tena."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Utafutaji haukupata vituo vyovyote. Thibitisha kuwa kitafutaji cha vituo cha USB kimechomekwa kwenye chanzo cha umeme na kuunganishwa katika chanzo cha mawimbi ya TV.\n\nKama unatumia antena ya hewani, rekebisha mkao wake au kule inakoelekea. Kwa matokeo bora zaidi, iweke juu, karibu na dirisha na utafute tena."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Haikupata vituo vyovyote. Thibitisha kwamba kitafuta vituo kimewashwa na kuunganishwa kwenye chanzo cha mawimbi ya TV.\n\nIkiwa unatumia antena ya hewani, rekebisha jinsi ilivyowekwa au inakoelekea. Ili upate matokeo bora zaidi, ipandishe juu na karibu na dirisha kisha utafute tena."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Tafuta tena"</item>
     <item msgid="2092797862490235174">"Nimemaliza"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Tafuta vituo vya TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Kuweka mipangilio ya kitafutaji cha vituo vya TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Kuweka mipangilio ya Kitafutaji cha Vituo cha USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Umeondoa kichagua programu cha USB cha TV."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Tafuta vituo vya TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Kuweka mipangilio ya kitafutaji cha vituo vya TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Kuweka mipangilio ya Kitafutaji cha Vituo vya TV kupitia USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Kuweka mipangilio ya Kitafutaji cha Vituo vya TV kupitia Mtandao"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Umeondoa kichagua programu cha USB cha TV."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Umeondoa kitafuta mitandao."</string>
 </resources>
diff --git a/usbtuner-res/values-ta/strings.xml b/usbtuner-res/values-ta-rIN/strings.xml
similarity index 73%
rename from usbtuner-res/values-ta/strings.xml
rename to usbtuner-res/values-ta-rIN/strings.xml
index dd09420..1c71722 100644
--- a/usbtuner-res/values-ta/strings.xml
+++ b/usbtuner-res/values-ta-rIN/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"டிவி ட்யூனர்"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB டிவி ட்யூனர்"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"இயக்கு"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"முடக்கு"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"நெட்வொர்க் டிவி டியூனர் (பீட்டா)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"செயலாக்கம் முடியும் வரை காத்திருக்கவும்"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"சேனல் மூலத்தைத் தேர்ந்தெடுக்கவும்"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"சிக்னல் இல்லை"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g>க்கு ட்யூன் செய்ய முடியவில்லை"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ட்யூன் செய்ய முடியவில்லை"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ட்யூனர் மென்பொருள் சமீபத்தில் புதுப்பிக்கப்பட்டது. சேனல்களை மீண்டும் ஸ்கேன் செய்யவும்."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ஆடியோவை இயக்க, சாதன ஒலி அமைப்புகளில் \"சரவுண்ட் சவுண்ட்\" என்பதை இயக்கவும்"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"ஆடியோவை இயக்க முடியவில்லை. வேறு டிவியைப் பயன்படுத்தவும்"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"சேனல் ட்யூனர் அமைவு"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"டிவி ட்யூனர் அமைவு"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB சேனல் ட்யூனர் அமைவு"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"நெட்வொர்க் டியூனர் அமைவு"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"டிவி சிக்னல் மூலத்துடன் உங்கள் டிவி இணைக்கப்பட்டுள்ளதைச் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதிகமான சேனல்களைப் பெறுவதற்காக அதன் இடம் அல்லது திசையைச் சரிசெய்ய வேண்டியிருக்கலாம். இன்னும் சிறப்பான முடிவுகளுக்கு, அதை உயரமான இடத்தில் ஜன்னலுக்கு அருகே வைக்கவும்."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB ட்யூனர் செருகப்பட்டுள்ளதையும் டிவி சிக்னல் மூலத்துடன் இணைக்கப்பட்டுள்ளதையும் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதிகமான சேனல்களைப் பெறுவதற்காக அதன் இடம் அல்லது திசையைச் சரிசெய்ய வேண்டியிருக்கலாம். இன்னும் சிறப்பான முடிவுகளுக்கு, அதை உயரமான இடத்தில் ஜன்னலுக்கு அருகே வைக்கவும்."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"நெட்வொர்க் டியூனர் ஆன் செய்யப்பட்டுள்ளதையும் டிவி சிக்னல் மூலத்துடன் இணைக்கப்பட்டுள்ளதையும் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதிகமான சேனல்களைப் பெறுவதற்காக அதன் இடம் அல்லது திசையைச் சரிசெய்ய வேண்டியிருக்கலாம். இன்னும் சிறப்பான முடிவுகளுக்கு, அதை உயரமான இடத்தில் ஜன்னலுக்கு அருகே வைக்கவும்."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"தொடர்க"</item>
     <item msgid="727245208787621142">"இப்போது வேண்டாம்"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"சேனல் அமைவை மீண்டும் இயக்கவா?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"இவ்வாறு செய்வதால் டிவி ட்யூனர் மூலம் கண்டறிந்த சேனல்கள் அகற்றப்படுவதுடன், புதிய சேனல்களுக்காக மீண்டும் ஸ்கேன் செய்யும்.\n\nடிவி சிக்னல் மூலத்துடன் உங்கள் டிவி இணைக்கப்பட்டுள்ளதைச் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதிகமான சேனல்களைப் பெறுவதற்காக அதன் இடம் அல்லது திசையைச் சரிசெய்ய வேண்டியிருக்கலாம். இன்னும் சிறப்பான முடிவுகளுக்கு, அதை உயரமான இடத்தில் ஜன்னலுக்கு அருகே வைக்கவும்."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"இவ்வாறு செய்வதால் USB ட்யூனர் மூலம் கண்டறிந்த சேனல்கள் அகற்றப்படுவதுடன், புதிய சேனல்களுக்காக மீண்டும் ஸ்கேன் செய்யும்.\n\nUSB ட்யூனர் செருகப்பட்டுள்ளதையும் டிவி சிக்னல் மூலத்துடன் இணைக்கப்பட்டுள்ளதையும் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதிகமான சேனல்களைப் பெறுவதற்காக அதன் இடம் அல்லது திசையைச் சரிசெய்ய வேண்டியிருக்கலாம். இன்னும் சிறப்பான முடிவுகளுக்கு, அதை உயரமான இடத்தில் ஜன்னலுக்கு அருகே வைக்கவும்."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"இது நெட்வொர்க் டியூனரிலிருந்து கண்டறிந்த சேனல்களை அகற்றும் மற்றும் புதிய சேனல்களுக்காக மீண்டும் ஸ்கேன் செய்யும்.\n\nநெட்வொர்க் டியூனர் ஆன் செய்யப்பட்டுள்ளதையும் டிவி சிக்னல் மூலத்துடன் இணைக்கப்பட்டுள்ளதையும் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதிகமான சேனல்களைப் பெறுவதற்காக, அதன் இடம் அல்லது திசையைச் சரிசெய்ய வேண்டியிருக்கலாம். இன்னும் சிறப்பான முடிவுகளுக்கு, உயரமான இடத்தில், ஜன்னலுக்கு அருகில் வைக்கவும்."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"தொடர்க"</item>
     <item msgid="235450158666155406">"ரத்துசெய்"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"டிவி ட்யூனர் அமைவு"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB சேனல் ட்யூனர் அமைவு"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"நெட்வொர்க் சேனல் டியூனர் அமைவு"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"இதற்குச் சில நிமிடங்கள் ஆகலாம்"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ட்யூனர் தற்காலிகமாகக் கிடைக்கவில்லை அல்லது ரெக்கார்டு செய்வதற்காக ஏற்கனவே பயன்படுத்தப்படுகிறது."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"சேனல்கள் இல்லை"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"ஸ்கேன் செய்ததில் சேனல்கள் எவையும் கண்டறியப்படவில்லை. டிவி சிக்னல் மூலத்துடன் உங்கள் டிவி இணைக்கப்பட்டுள்ளதைச் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதன் இடம் அல்லது திசையைச் சரிசெய்யவும். இன்னும் சிறப்பான முடிவுகளுக்கு, அதை உயரமான இடத்தில் ஜன்னலுக்கு அருகே வைத்து, மீண்டும் ஸ்கேன் செய்யவும்."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"ஸ்கேன் செய்ததில் சேனல்கள் எவையும் கண்டறியப்படவில்லை. USB ட்யூனர் செருகப்பட்டுள்ளதையும் டிவி சிக்னல் மூலத்துடன் இணைக்கப்பட்டுள்ளதையும் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதன் இடம் அல்லது திசையைச் சரிசெய்யவும். இன்னும் சிறப்பான முடிவுகளுக்கு, அதை உயரமான இடத்தில் ஜன்னலுக்கு அருகே வைத்து, மீண்டும் ஸ்கேன் செய்யவும்."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"ஸ்கேன் செய்ததில் சேனல்கள் எதுவும் கண்டறியப்படவில்லை. நெட்வொர்க் டியூனர் ஆன் செய்யப்பட்டுள்ளதையும் டிவி சிக்னல் மூலத்துடன் இணைக்கப்பட்டுள்ளதையும் சரிபார்க்கவும்.\n\nஆன்டெனாவைப் பயன்படுத்தினால், அதன் இடம் அல்லது திசையைச் சரிசெய்யவும். இன்னும் சிறப்பான முடிவுகளுக்கு, அதை உயரமான இடத்தில் ஜன்னலுக்கு அருகே வைத்து, மீண்டும் ஸ்கேன் செய்யவும்."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"மீண்டும் ஸ்கேன் செய்"</item>
     <item msgid="2092797862490235174">"முடிந்தது"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"டிவி சேனல்களை ஸ்கேன் செய்"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"டிவி ட்யூனர் அமைவு"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB டிவி ட்யூனர் அமைவு"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB டிவி ட்யூனர் வெளியே எடுக்கப்பட்டது."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"டிவி சேனல்களைத் தேடுக"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"டிவி டியூனர் அமைவு"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB டிவி டியூனர் அமைவு"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"நெட்வொர்க் டிவி டியூனர் அமைவு"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB டிவி ட்யூனர் துண்டிக்கப்பட்டது."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"நெட்வொர்க் ட்யூனர் துண்டிக்கப்பட்டது."</string>
 </resources>
diff --git a/usbtuner-res/values-te/strings.xml b/usbtuner-res/values-te-rIN/strings.xml
similarity index 73%
rename from usbtuner-res/values-te/strings.xml
rename to usbtuner-res/values-te-rIN/strings.xml
index a80bd1c..fb6bcf3 100644
--- a/usbtuner-res/values-te/strings.xml
+++ b/usbtuner-res/values-te-rIN/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"టీవీ ట్యూనర్"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB టీవీ ట్యూనర్"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"ఆన్ చేయి"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"ఆఫ్ చేయి"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"నెట్‌వర్క్ టీవీ ట్యూనర్ (బీటా)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"దయచేసి ప్రాసెస్ చేయడం పూర్తయ్యే వరకు వేచి ఉండండి"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"మీ ఛానెల్ మూలాన్ని ఎంచుకోండి"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"సిగ్నల్ లేదు"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g>కి ట్యూన్ చేయడంలో విఫలమైంది"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ట్యూన్ చేయడంలో విఫలమైంది"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ట్యూనర్ సాఫ్ట్‌వేర్ ఇటీవల నవీకరించబడింది. దయచేసి ఛానెల్‌లను మళ్లీ స్కాన్ చేయండి."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"ఆడియోను ప్రారంభించడానికి సిస్టమ్ శబ్ద సెట్టింగ్‌ల్లో పరిసర వ్యాప్త శబ్దాన్ని ప్రారంభించండి"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"ఆడియోను ప్లే చేయడం సాధ్యపడదు. దయచేసి మరో టీవీలో ప్రయత్నించండి"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"ఛానెల్ ట్యూనర్ సెటప్"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"టీవీ ట్యూనర్ సెటప్"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB ఛానెల్ ట్యూనర్ సెటప్"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"నెట్‍వర్క్ ట్యూనర్ సెటప్"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"టీవీ.సిగ్నల్ సోర్స్‌కు మీ టీవీ కనెక్ట్ చేయబడిందని ధృవపరుచుకోండి.\n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, మీరు మరిన్ని ఛానెల్‌లను స్వీకరించడానికి దాని స్థానాన్ని లేదా దిశను మార్చాల్సి రావచ్చు. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచండి."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB ట్యూనర్ ప్లగిన్ చేయబడి, టీవీ సిగ్నల్ సోర్స్‌కు కనెక్ట్ చేయబడినట్లు ధృవపరుచుకోండి.\n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, మీరు మరిన్ని ఛానెల్‌లను స్వీకరించడానికి దాని స్థానాన్ని లేదా దిశను మార్చాల్సి రావచ్చు. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచండి."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"నెట్‍వర్క్ ట్యూనర్ పవర్ ఆన్ చేయబడి, టీవీ సిగ్నల్ సోర్స్‌కు కనెక్ట్ చేయబడినట్లు ధృవపరుచుకోండి.\n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, మీరు మరిన్ని ఛానెల్‌లను స్వీకరించడానికి దాని స్థానాన్ని లేదా దిశను మార్చాల్సి రావచ్చు. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచండి."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"కొనసాగించు"</item>
     <item msgid="727245208787621142">"ఇప్పుడు కాదు"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"ఛానెల్ సెటప్‌ను మళ్లీ అమలు చేయాలా?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"ఇది టీవీ ట్యూనర్ నుండి కనుగొన్న ఛానెల్‌లను తీసివేస్తుంది మరియు మళ్లీ కొత్త ఛానెల్‌ల కోసం స్కాన్ చేస్తుంది.\n\nటీవీ సిగ్నల్ సోర్స్‌కు మీ టీవీ కనెక్ట్ చేయబడిందని ధృవపరుచుకోండి.\n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, మీరు మరిన్ని ఛానెల్‌లను స్వీకరించడానికి దాని స్థానాన్ని లేదా దిశను మార్చాల్సి రావచ్చు. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచండి."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"ఇది USB ట్యూనర్ నుండి కనుగొన్న ఛానెల్‌లను తీసివేస్తుంది మరియు మళ్లీ కొత్త ఛానెల్‌ల కోసం స్కాన్ చేస్తుంది.\n\nUSB ట్యూనర్ ప్లగిన్ చేయబడి, టీవీ సిగ్నల్ సోర్స్‌కు కనెక్ట్ చేయబడిందని ధృవపరుచుకోండి.\n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, మీరు మరిన్ని ఛానెల్‌లను స్వీకరించడానికి దాని స్థానాన్ని లేదా దిశను మార్చాల్సి రావచ్చు. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచండి."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"ఇది నెట్‍వర్క్ ట్యూనర్ నుండి కనుగొన్న ఛానెల్‌లను తీసివేస్తుంది మరియు మళ్లీ కొత్త ఛానెల్‌ల కోసం స్కాన్ చేస్తుంది.\n\nనెట్‍వర్క్ ట్యూనర్ పవర్ ఆన్ చేయబడి, టీవీ సిగ్నల్ సోర్స్‌కు కనెక్ట్ చేయబడిందని ధృవపరుచుకోండి.\n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, మీరు మరిన్ని ఛానెల్‌లను స్వీకరించడానికి దాని స్థానాన్ని లేదా దిశను మార్చాలి. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచండి."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"కొనసాగించు"</item>
     <item msgid="235450158666155406">"రద్దు చేయి"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"టీవీ ట్యూనర్ సెటప్"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB ఛానెల్ ట్యూనర్ సెటప్"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"నెట్‍వర్క్ ఛానెల్ ట్యూనర్ సెటప్"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"దీనికి కొన్ని నిమిషాలు పట్టవచ్చు"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ట్యూనర్ తాత్కాలికంగా అందుబాటులో లేదు లేదా ఇప్పటికే రికార్డింగ్ ద్వారా ఉపయోగించబడుతోంది."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"ఛానెల్‌లు ఏవీ కనుగొనబడలేదు"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"స్కాన్‌లో ఏ ఛానెల్ కనుగొనబడలేదు. టీవీ సిగ్నల్ సోర్స్‌కి మీ టీవీ కనెక్ట్ చేయబడిందని ధృవపరుచుకోండి. \n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, దాని స్థానాన్ని లేదా దిశను సర్దుబాటు చేయండి. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచి, ఆపై మళ్లీ స్కాన్ చేయండి."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"స్కాన్‌లో ఛానెల్‌లు ఏవీ కనుగొనబడలేదు. USB ట్యూనర్ ప్లగిన్ చేయబడి, టీవీ సిగ్నల్ సోర్స్‌కు కనెక్ట్ చేయబడిందని ధృవపరుచుకోండి.\n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, దాని స్థానాన్ని లేదా దిశను సర్దుబాటు చేయండి. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచి, ఆపై మళ్లీ స్కాన్ చేయండి."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"స్కాన్‌లో ఛానెల్‌లు ఏవీ కనుగొనబడలేదు. నెట్‍వర్క్ ట్యూనర్ పవర్ ఆన్ చేయబడి, టీవీ సిగ్నల్ సోర్స్‌కు కనెక్ట్ చేయబడిందని ధృవపరుచుకోండి.\n\nప్రసారాల కోసం యాంటెన్నాను ఉపయోగిస్తుంటే, దాని స్థానాన్ని లేదా దిశను సర్దుబాటు చేయండి. ఉత్తమ ఫలితాల కోసం, దాన్ని ఎత్తులో కిటికీకి దగ్గరగా ఉంచి, ఆపై మళ్లీ స్కాన్ చేయండి."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"మళ్లీ స్కాన్ చేయి"</item>
     <item msgid="2092797862490235174">"పూర్తయింది"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"టీవీ ఛానెల్‌ల కోసం స్కాన్ చేయండి"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"టీవీ ట్యూనర్ సెటప్"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB టీవీ ట్యూనర్ సెటప్"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB టీవీ ట్యూనర్ డిస్‌కనెక్ట్ చేయబడింది."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"టీవీ ఛానెల్‌ల కోసం స్కాన్ చేయండి"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"టీవీ ట్యూనర్ సెటప్"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB టీవీ ట్యూనర్ సెటప్"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"నెట్‍వర్క్ టీవీ ట్యూనర్ సెటప్"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB టీవీ ట్యూనర్ డిస్‌కనెక్ట్ చేయబడింది."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"నెట్‌వర్క్ ట్యూనర్ డిస్‌కనెక్ట్ చేయబడింది."</string>
 </resources>
diff --git a/usbtuner-res/values-th/strings.xml b/usbtuner-res/values-th/strings.xml
index 217520d..703c0f0 100644
--- a/usbtuner-res/values-th/strings.xml
+++ b/usbtuner-res/values-th/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ตัวรับสัญญาณทีวี"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"ตัวรับสัญญาณทีวีแบบ USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"เปิด"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"ปิด"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"ตัวรับสัญญาณทีวีเครือข่าย (เบต้า)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"โปรดรอให้การดำเนินการหยุดลงสักครู่"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"เลือกแหล่งที่มาของช่อง"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"ไม่มีสัญญาณ"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"ไม่สามารถรับสัญญาณ <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ไม่สามารถรับสัญญาณ"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ซอฟต์แวร์ตัวรับสัญญาณมีการอัปเดตเมื่อเร็วๆ นี้ โปรดสแกนช่องอีกครั้ง"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"เปิดใช้เสียงเซอร์ราวด์ในการตั้งค่าเสียงของระบบเพื่อเปิดใช้เสียง"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"เล่นเสียงไม่ได้ โปรดลองทีวีเครื่องอื่น"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"ตั้งค่าตัวรับสัญญาณช่อง"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"ตั้งค่าตัวรับสัญญาณทีวี"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"ตั้งค่าตัวรับสัญญาณช่องแบบ USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"ตั้งค่าตัวรับสัญญาณเครือข่าย"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"โปรดตรวจสอบว่าทีวีของคุณเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากใช้เสาอากาศแบบผ่านอากาศ คุณอาจต้องปรับตำแหน่งและทิศทางเพื่อรับช่องให้ได้มากที่สุด เพื่อผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่าง"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"โปรดตรวจสอบว่าได้เสียบปลั๊กตัวรับสัญญาณแบบ USB และเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากใช้เสาอากาศแบบผ่านอากาศ คุณอาจต้องปรับตำแหน่งหรือทิศทางเพื่อรับช่องให้ได้มากที่สุด เพื่อผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่าง"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"โปรดตรวจสอบว่าตัวรับสัญญาณเครือข่ายเปิดอยู่และเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากใช้เสาอากาศแบบผ่านอากาศ (OTA) คุณอาจต้องปรับตำแหน่งหรือทิศทางเพื่อรับช่องให้ได้มากที่สุด เพื่อผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่าง"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"ต่อไป"</item>
     <item msgid="727245208787621142">"ข้ามไปก่อน"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"ต้องการเริ่มการตั้งค่าช่องอีกครั้งใช่ไหม"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"วิธีนี้จะนำช่องที่พบจากตัวรับสัญญาณทีวีออกและสแกนหาช่องใหม่อีกครั้ง\n\nโปรดตรวจสอบว่าทีวีของคุณเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากใช้เสาอากาศแบบผ่านอากาศ คุณอาจต้องปรับตำแหน่งและทิศทางเพื่อรับช่องให้ได้มากที่สุด เพื่อผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่าง"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"วิธีนี้จะนำช่องที่พบจากตัวรับสัญญาณแบบ USB ออกและสแกนหาช่องใหม่อีกครั้ง\n\nโปรดตรวจสอบว่าได้เสียบปลั๊กตัวรับสัญญาณแบบ USB และเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากใช้เสาอากาศแบบผ่านอากาศ คุณอาจต้องปรับตำแหน่งหรือทิศทางเพื่อรับช่องให้ได้มากที่สุด เพื่อผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่าง"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"การดำเนินการนี้จะนำช่องที่พบจากตัวรับสัญญาณเครือข่ายออกแล้วสแกนหาช่องใหม่อีกครั้ง\n\nโปรดตรวจสอบว่าตัวรับสัญญาณเครือข่ายเปิดอยู่และเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากใช้เสาอากาศแบบผ่านอากาศ (OTA) คุณอาจต้องปรับตำแหน่งหรือทิศทางเพื่อรับช่องให้ได้มากที่สุด เพื่อผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่าง"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"ต่อไป"</item>
     <item msgid="235450158666155406">"ยกเลิก"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"ตั้งค่าตัวรับสัญญาณทีวี"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"ตั้งค่าตัวรับสัญญาณช่องแบบ USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"ตั้งค่าตัวรับสัญญาณช่องเครือข่าย"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"อาจใช้เวลาหลายนาที"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ตัวรับสัญญาณไม่สามารถใช้ได้ชั่วคราว หรือถูกใช้ในการบันทึกแล้ว"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"ไม่พบช่อง"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"สแกนไม่พบช่องใดเลย โปรดตรวจสอบว่าทีวีของคุณเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากคุณใช้เสาอากาศแบบผ่านอากาศ ให้ปรับตำแหน่งและทิศทาง เพื่อผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่างแล้วสแกนอีกครั้ง"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"สแกนไม่พบช่องใดเลย โปรดตรวจสอบว่าได้เสียบปลั๊กตัวรับสัญญาณแบบ USB และเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากคุณใช้เสาอากาศแบบผ่านอากาศ ให้ปรับตำแหน่งหรือทิศทาง เพื่อให้ได้ผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่างแล้วสแกนอีกครั้ง"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"สแกนไม่พบช่องใดเลย โปรดตรวจสอบว่าตัวรับสัญญาณเครือข่ายเปิดอยู่และเชื่อมต่อกับแหล่งสัญญาณทีวีแล้ว\n\nหากใช้เสาอากาศแบบผ่านอากาศ (OTA) ให้ปรับตำแหน่งหรือทิศทาง เพื่อผลลัพธ์ที่ดีที่สุด ให้วางไว้บนที่สูงใกล้หน้าต่างแล้วสแกนอีกครั้ง"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"สแกนอีกครั้ง"</item>
     <item msgid="2092797862490235174">"เสร็จสิ้น"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"สแกนหาช่องทีวี"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"ตั้งค่าตัวรับสัญญาณทีวี"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"ตั้งค่าตัวรับสัญญาณทีวีแบบ USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"ยกเลิกการเชื่อมต่อตัวรับสัญญาณทีวีผ่าน USB แล้ว"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"สแกนหาช่องทีวี"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"ตั้งค่าตัวรับสัญญาณทีวี"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"ตั้งค่าตัวรับสัญญาณทีวีแบบ USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"ตั้งค่าตัวรับสัญญาณทีวีเครือข่าย"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"ยกเลิกการเชื่อมต่อตัวรับสัญญาณทีวีผ่าน USB แล้ว"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"ยกเลิกการเชื่อมต่อตัวรับสัญญาณเครือข่ายแล้ว"</string>
 </resources>
diff --git a/usbtuner-res/values-tl/strings.xml b/usbtuner-res/values-tl/strings.xml
index 7a0ce82..52c99ea 100644
--- a/usbtuner-res/values-tl/strings.xml
+++ b/usbtuner-res/values-tl/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV Tuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV Tuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"I-on"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"I-off"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Network TV Tuner (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Mangyaring maghintay na matapos ang pagpoproseso"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Piliin ang pinagmulan ng iyong channel"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Walang Signal"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Hindi na-tune sa <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Hindi na-tune"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Na-update kamakailan ang software ng tuner. Paki-scan muli ang mga channel."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"I-enable ang surround sound sa mga setting ng tunog ng system upang ma-enable ang audio"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Hindi ma-play ang audio. Mangyaring sumubok ng ibang TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Setup ng channel tuner"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Setup ng TV Tuner"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Setup ng USB channel tuner"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Pag-set up ng network tuner"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"I-verify na nakakonekta ang iyong TV sa isang TV signal source.\n\nKung gumagamit ng over-the-air antenna, maaaring kailanganin mong ayusin ang pagkakalagay o direksyon nito upang makuha ang pinakamaraming channel. Para sa mga pinakamainam na resulta, ilagay ito sa mataas na lugar at malapit sa isang bintana."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"I-verify na nakasaksak at nakakonekta ang USB tuner sa isang TV source signal.\n\nKung gumagamit ka ng isang over-the-air antenna, maaaring kailanganin mong ayusin ang pagkakalagay o direksyon nito upang makuha ang pinakamaraming channel. Para sa mga pinakamainam na resulta, ilagay ito sa isang mataas na lugar at malapit sa isang bintana."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"I-verify na naka-on ang network tuner at nakakonekta sa isang pinagmumulan ng TV signal.\n\nKung gumagamit ng over-the-air na antenna, maaaring kailanganin mong ayusin ang pagkakalagay o direksyon nito upang masagap ang karamihan ng mga channel. Para sa mga pinakamainam na resulta, ilagay ito sa mataas na lugar at malapit sa bintana."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Magpatuloy"</item>
     <item msgid="727245208787621142">"Hindi ngayon"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Gusto mo bang muling patakbuhin ang pag-set up ng channel?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Aalisin nito ang mga nakitang channel mula sa TV tuner at mag-scan muli para sa mga bagong channel.\n\nI-verify na nakakonekta ang iyong TV sa isang TV signal source.\n\nKung gumagamit ka ng over-the-air antenna, maaaring kailanganin mong ayusin ang pagkakalagay o direksyon nito upang makuha ang pinakamaraming channel. Para sa mga pinakamainam na resulta, ilagay ito sa mataas na lugar at malapit sa isang bintana."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Aalisin nito ang mga channel na nahanap mula sa USB tuner at mag-scan muli para sa mga bagong channel.\n\nI-verify na nakasaksak at nakakonekta ang USB tuner sa isang TV source signal.\n\nKung gumagamit ng over-the-air antenna, maaaring kailanganin mong ayusin ang pagkakalagay o direksyon nito upang makuha ang pinakamaraming channel. Para sa mga pinakamainam na resulta, ilagay ito sa isang mataas na lugar at malapit sa isang bintana."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Aalisin nito ang mga nahanap na channel sa network tuner at muling magsa-scan ng mga bagong channel.\n\nI-verify na naka-on ang network tuner at nakakonekta sa isang pinagmumulan ng TV signal.\n\nKung gumagamit ng over-the-air na antenna, maaaring kailanganin mong ayusin ang pagkakalagay o direksyon nito upang masagap ang karamihan ng mga channel. Para sa mga pinakamainam na resulta, ilagay ito sa mataas na lugar at malapit sa bintana."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Magpatuloy"</item>
     <item msgid="235450158666155406">"Kanselahin"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Setup ng TV tuner"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Setup ng USB channel tuner"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Pag-set up ng network channel tuner"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Maaari itong tumagal ng ilang minuto"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Pansamantalang hindi available ang Tuner o ginagamit na ito ng recording."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Walang nakitang Mga Channel"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Hindi nakahanap ng anumang mga channel ang pag-scan. I-verify na nakakonekta ang iyong TV sa isang TV signal source.\n\nKung gumagamit ka ng over-the-air antenna, ayusin ang pagkakalagay o direksyon nito. Para sa mga pinakamainam na resulta, ilagay ito sa mataas na lugar malapit sa isang bintana at mag-scan muli."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Walang nahanap na anumang mga channel noong nag-scan. I-verify na nakasaksak at nakakonekta ang USB tuner sa isang TV signal source.\n\nKung gumagamit ka ng over-the-air antenna, ayusin ang pagkakalagay o direksyon nito. Para sa mga pinakamainam na resulta, ilagay ito sa isang mataas na lugar at malapit sa isang bintana mag-scan muli."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Walang nahanap na channel sa pag-scan. I-verify na naka-on ang network tuner at nakakonekta sa isang pinagmumulan ng TV signal.\n\nKung gumagamit ng over-the-air na antenna, ayusin ang pagkakalagay o direksyon nito. Para sa mga pinakamainam na resulta, ilagay ito sa mataas na lugar at malapit sa bintana at muling mag-scan."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Muling mag-scan"</item>
     <item msgid="2092797862490235174">"Tapos Na"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Mag-scan ng mga channel sa TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Setup ng TV Tuner"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Setup ng USB TV Tuner"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Nadiskonekta ang USB TV tuner."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Mag-scan ng mga channel sa TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Setup ng TV Tuner"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Setup ng USB TV Tuner"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Setup ng Network TV Tuner"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Nadiskonekta ang USB TV tuner."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Nadiskonekta ang network tuner."</string>
 </resources>
diff --git a/usbtuner-res/values-tr/strings.xml b/usbtuner-res/values-tr/strings.xml
index 29910f9..5196bfa 100644
--- a/usbtuner-res/values-tr/strings.xml
+++ b/usbtuner-res/values-tr/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV Kanal Ayarlayıcı"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV Kanal Ayarlayıcı"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Açık"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Kapalı"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Ağ TV Kanal Ayarlayıcı (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Lütfen işlemin tamamlanmasını bekleyin"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Kanal kaynağınızı seçin"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Sinyal Yok"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> adlı kanala ayarlanamadı"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Kanal ayarlanamadı"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Kanal ayarlayıcı yazılımı yakın zamanda güncellendi. Lütfen kanalları yeniden tarayın."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Sesi etkinleştirmek için sistemin ses ayarlarında surround sesi etkinleştirin"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Ses çalınamıyor. Lütfen başka bir TV deneyin"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Kanal ayarlayıcı kurulumu"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV Kanal Ayarlayıcı kurulumu"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB kanal ayarlayıcı kurulumu"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Ağ kanal ayarlayıcı kurulumu"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"TV\'nizin bir TV sinyal kaynağına bağlı olduğunu doğrulayın.\n\nHavadan yayın alan bir anten kullanıyorsanız en çok sayıda kanalı almak için antenin yerini veya yönünü ayarlamanız gerekebilir. En iyi sonucu elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirin."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB kanal ayarlayıcının takılı olduğunu ve bir TV sinyali kaynağına bağlandığını doğrulayın.\n\nHavadan yayın alan bir anten kullanıyorsanız en çok sayıda kanalı almak için antenin yerini veya yönünü ayarlamanız gerekebilir. En iyi sonucu elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirin."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Ağ kanal ayarlayıcının açık olduğunu ve TV sinyali alabileceği bir kaynağa bağlandığını doğrulayın.\n\nHavadan gelen yayını alacak bir anten kullanıyorsanız en fazla sayıda kanalı almak için antenin yerini veya yönünü ayarlamanız gerekebilir. En iyi sonuçları elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirin."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Devam"</item>
     <item msgid="727245208787621142">"Şimdi değil"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Kanal kurulumu yeniden çalıştırılsın mı?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Bu işlem, TV kanal ayarlayıcının bulduğu kanalları kaldıracak ve tekrar yeni kanallar arayacak.\n\nTV\'nizin bir TV sinyal kaynağına bağlı olduğunu doğrulayın.\n\nHavadan yayın alan bir anten kullanıyorsanız en çok sayıda kanalı almak için antenin yerini veya yönünü ayarlamanız gerekebilir. En iyi sonucu elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirin."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Bu işlem, USB kanal ayarlayıcıdan bulunan kanalları kaldıracak ve yeni kanallar için tekrar tarama yapacaktır.\n\nUSB kanal ayarlayıcının takılı olduğunu ve bir TV sinyali kaynağına bağlandığını doğrulayın.\n\nHavadan yayın alan bir anten kullanıyorsanız en çok sayıda kanalı almak için antenin yerini veya yönünü ayarlamanız gerekebilir. En iyi sonucu elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirin."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Bu işlem, bulunan kanalları ağ kanal ayarlayıcıdan kaldıracak ve yeni kanalların bulunması için tekrar tarama yapacak.\n\nAğ kanal ayarlayıcının açık olduğunu ve TV sinyali alabileceği bir kaynağa bağlandığını doğrulayın.\n\nHavadan gelen yayını alacak bir anten kullanıyorsanız en fazla sayıda kanalı almak için antenin yerini veya yönünü ayarlamanız gerekebilir. En iyi sonucu elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirin."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Devam"</item>
     <item msgid="235450158666155406">"İptal"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV kanal ayarlayıcı kurulumu"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB kanal ayarlayıcı kurulumu"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Ağ kanal ayarlayıcı kurulumu"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Bu işlem birkaç dakika sürebilir"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Kanal ayarlayıcı geçici olarak kullanılamıyor veya şu anda kayıt yapmak için kullanılıyor."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Hiçbir kanal bulunamadı"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Tarama işleminde hiçbir kanal bulunamadı. TV\'nizin bir TV sinyal kaynağına bağlı olduğunu doğrulayın.\n\nHavadan yayın alan bir anten kullanıyorsanız yerini veya yönünü ayarlayın. En iyi sonucu elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirerek tekrar tarayın."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Tarama işlemi herhangi bir kanal bulamadı. USB kanal ayarlayıcının takılı olduğunu ve bir TV sinyali kaynağına bağlandığını doğrulayın.\n\nHavadan yayın alan bir anten kullanıyorsanız yerini veya yönünü ayarlayın. En iyi sonucu elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirerek tekrar tarayın."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Taramada herhangi bir kanal bulunamadı. Ağ kanal ayarlayıcının açık olduğunu ve TV sinyali alabileceği bir kaynağa bağlandığını doğrulayın.\n\nHavadan gelen yayınları alacak bir anten kullanıyorsanız antenin yerini veya yönünü ayarlayın. En iyi sonucu elde etmek için anteni yüksek ve pencereye yakın bir yere yerleştirin."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Yeniden tara"</item>
     <item msgid="2092797862490235174">"Bitti"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"TV kanallarını tarayın"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV Kanal Ayarlayıcı kurulumu"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV Kanal Ayarlayıcı kurulumu"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB TV kanal ayarlayıcı bağlantısı kesildi."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"TV kanallarını tarayın"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV Kanal Ayarlayıcı kurulumu"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV Kanal Ayarlayıcı kurulumu"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Ağ TV Kanal Ayarlayıcı kurulumu"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB TV kanal ayarlayıcı bağlantısı kesildi."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Ağ kanal ayarlayıcı bağlantısı kesildi."</string>
 </resources>
diff --git a/usbtuner-res/values-uk/strings.xml b/usbtuner-res/values-uk/strings.xml
index cf7cc85..50c84ef 100644
--- a/usbtuner-res/values-uk/strings.xml
+++ b/usbtuner-res/values-uk/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"ТВ-тюнер"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"ТВ-тюнер USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Увімкнути"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Вимкнути"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Мережевий ТВ-тюнер (БЕТА-ВЕРСІЯ)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Зачекайте, доки завершиться пошук"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Виберіть джерело каналу"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Немає сигналу"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Не вдалося налаштувати канал <xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Не вдалося налаштувати"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Програмне забезпечення тюнера нещодавно оновлено. Проскануйте канали знову."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Увімкнути об’ємний звук у налаштуваннях системи, щоб слухати аудіо"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Не вдається відтворити відео. Спробуйте на іншому телевізорі"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Налаштування тюнера"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Налаштування ТВ-тюнера"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Налаштування USB-тюнера"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Налаштування мережевого тюнера"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Переконайтеся, що ви під’єднали телевізор до джерела вхідного телевізійного сигналу.\n\nЯкщо ви користуєтесь ефірною антеною, змініть її положення,щоб знайти більше каналів. Розмістіть антену вище та біля вікна."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Переконайтеся, що ви підключили USB-тюнер і під’єднали джерело вхідного телевізійного сигналу.\n\nЯкщо ви користуєтесь ефірною антеною, змініть її положення, щоб знайти більше каналів. Розмістіть антену вище та біля вікна."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Переконайтеся, що мережевий тюнер увімкнено та під’єднано до джерела телевізійного сигналу.\n\nЯкщо у вас ефірна антена, змініть її положення. Розмістіть антену вище та біля вікна й повторіть спробу."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Продовжити"</item>
     <item msgid="727245208787621142">"Не зараз"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Відновити налаштування каналу?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Канали, знайдені за допомогою ТВ-тюнера, буде видалено. Пошук почнеться знову.\n\nПереконайтеся, що ви під’єднали телевізор до джерела вхідного телевізійного сигналу.\n\nЯкщо ви користуєтесь ефірною антеною, змініть її положення, щоб знайти більше каналів. Розмістіть антену вище та біля вікна й повторіть спробу."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Канали, знайдені за допомогою USB-тюнера, буде видалено. Пошук почнеться знову.\n\nПереконайтеся, що ви підключили USB-тюнер і під’єднали джерело вхідного телевізійного сигналу.\n\nЯкщо ви користуєтесь ефірною антеною, змініть її положення, щоб знайти більше каналів. Розмістіть антену вище та біля вікна."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Канали, знайдені мережевим тюнером, буде видалено. Пошук почнеться знову.\n\nПереконайтеся, що мережевий тюнер увімкнено та під’єднано до джерела телевізійного сигналу.\n\nЯкщо у вас ефірна антена, змініть її положення. Розмістіть антену вище та біля вікна й повторіть спробу."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Продовжити"</item>
     <item msgid="235450158666155406">"Скасувати"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Налаштування ТВ-тюнера"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Налаштування USB-тюнера"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Налаштування мережевого тюнера"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Це може зайняти декілька хвилин"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Тюнер тимчасово недоступний або вже використовується для запису."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -82,12 +82,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Канали не знайдено"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Канали не знайдено. Переконайтеся, що ви під’єднали телевізор до джерела вхідного телевізійного сигналу.\n\nЯкщо ви користуєтесь ефірною антеною, змініть її положення. Розмістіть антену вище та біля вікна й повторіть спробу."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Канали не знайдено. Переконайтеся, що ви підключили USB-тюнер і під’єднали джерело вхідного телевізійного сигналу.\n\nЯкщо ви користуєтесь ефірною антеною, змініть її положення. Розмістіть антену вище та біля вікна й повторіть спробу."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Каналів не знайдено. Переконайтеся, що мережевий тюнер увімкнено та під’єднано до джерела телевізійного сигналу.\n\nЯкщо у вас ефірна антена, змініть її положення. Розмістіть антену вище та біля вікна й повторіть спробу."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Шукати знову"</item>
     <item msgid="2092797862490235174">"Готово"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Пошук телевізійних каналів"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Налаштування ТВ-тюнера"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Налаштування ТВ-тюнера USB"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"ТВ-тюнер USB від’єднано."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Пошук телевізійних каналів"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Налаштування ТВ-тюнера"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Налаштування ТВ-тюнера USB"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Налаштування мережевого ТВ-тюнера"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"ТВ-тюнер USB від’єднано."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Мережевий тюнер від’єднано."</string>
 </resources>
diff --git a/usbtuner-res/values-ur/strings.xml b/usbtuner-res/values-ur-rPK/strings.xml
similarity index 74%
rename from usbtuner-res/values-ur/strings.xml
rename to usbtuner-res/values-ur-rPK/strings.xml
index 68c85d0..49dc9e3 100644
--- a/usbtuner-res/values-ur/strings.xml
+++ b/usbtuner-res/values-ur-rPK/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"‏TV ٹیونر"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"‏USB TV ٹیونر"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"آن"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"آف"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"‏نیٹ ورک TV ٹیونر (بی ٹا)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"براہ کرم کارروائی ختم ہونے کا انتظار کریں"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"اپنے چینل کا ماخذ منتخب کریں"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"کوئی سگنل نہیں ہے"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"<xliff:g id="CHANNEL_NAME">%s</xliff:g> پر ٹیون ہونے میں ناکام ہوگیا"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"ٹیون کرنے میں ناکام ہو گیا"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"ٹیونر سافٹ ویئر حال ہی میں اپ ڈیٹ کیا گیا ہے۔ براہ کرم چینلز کو دوبارہ اسکین کریں۔"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"آڈیو کو فعال کرنے کیلئے سسٹم کی آواز کی ترتیبات میں محیط آواز فعال کریں"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"آڈیو نہیں چل رہی۔ براہ کرم کوئی اور ٹی وی آزمائیں"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"چینل ٹیونر سیٹ اپ"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"‏TV ٹیونر سیٹ اپ"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"‏USB چینل ٹیونر سیٹ اپ"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"نیٹ ورک ٹیونر سیٹ اپ"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"‏اپنے TV کے کسی TV سگنل ماخذ سے منسلک ہونے کی توثیق کریں۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں تو زیادہ تر چینلز موصول کرنے کیلئے آپ کو اس کا مقام یا سمت ایڈجسٹ کرنے کی ضرورت پیش آ سکتی ہے۔ بہترین نتائج کیلئے اسے اونچی جگہ اور کھڑکی کے پاس رکھیں۔"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"‏USB ٹیونر کے پلگ ان ہونے اور TV سگنل ماخذ سے منسلک ہونے کی توثیق کریں۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں تو زیادہ تر چینلز موصول کرنے کیلئے آپ کو اس کا مقام یا سمت ایڈجسٹ کرنے کی ضرورت پیش آ سکتی ہے۔ بہترین نتائج کیلئے اسے اونچی جگہ اور کھڑکی کے پاس رکھیں۔"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"‏نیٹ ورک ٹیونر کے آن ہونے اور TV سگنل ماخذ سے منسلک ہونے کی توثیق کریں۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں تو زیادہ تر چینلز موصول کرنے کیلئے آپ کو اس کا مقام یا سمت ایڈجسٹ کرنے کی ضرورت پیش آ سکتی ہے۔ بہترین نتائج کیلئے اسے اونچی جگہ اور کھڑکی کے پاس رکھیں۔"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"جاری رکھیں"</item>
     <item msgid="727245208787621142">"ابھی نہیں"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"چینل سیٹ اپ دوبارہ چلائیں؟"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"‏یہ TV ٹیونر سے ملے چینلز ہٹا دے گا اور دوبارہ نئے چینلز کیلئے اسکین کرے گا۔\n\nاپنے TV کے کسی سگنل ماخذ سے منسلک ہونے کی توثیق کریں۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں تو زیادہ تر چینلز موصول کرنے کیلئے آپ کو اس کا مقام یا سمت ایڈجسٹ کرنے کی ضرورت پیش آ سکتی ہے۔ بہترین نتائج کیلئے اسے اونچی جگہ اور کھڑکی کے پاس رکھیں۔"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"‏یہ USB ٹیونر سے ملے چینلز ہٹا دے گا اور دوبارہ نئے چینلز کیلئے اسکین کرے گا۔\n\nTV ٹیونر کے پلگ ان ہونے اور سگنل ماخذ سے منسلک ہونے کی توثیق کریں۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں تو زیادہ تر چینلز موصول کرنے کیلئے آپ کو اس کا مقام یا سمت ایڈجسٹ کرنے کی ضرورت پیش آ سکتی ہے۔ بہترین نتائج کیلئے اسے اونچی جگہ اور کھڑکی کے پاس رکھیں۔"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"‏یہ نیٹ ورک ٹیونر سے ملنے والے چیلنز ہٹا دے گا اور دوبارہ نئے چینلز کیلئے اسکین کرے گا۔\n\nTV ٹیونر کے آن ہونے اور سگنل ماخذ سے منسلک ہونے کی توثیق کریں۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں، تو زیادہ تر چینلز موصول کرنے کیلئے آپ کو اس کی مقام بندی یا سمت ایڈجسٹ کرنے کی ضرورت پیش آ سکتی ہے۔ بہترین نتائج کیلئے اسے اونچی جگہ اور کھڑکی کے پاس رکھیں۔"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"جاری رکھیں"</item>
     <item msgid="235450158666155406">"منسوخ کریں"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"‏TV ٹیونر سیٹ اپ"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"‏USB چینل ٹیونر سیٹ اپ"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"نیٹ ورک چینل ٹیونر سیٹ اپ"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"اس میں کئی منٹ لگ سکتے ہیں"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"ٹیونر عارضی طور پر غیر دستیاب ہے یا پہلے سے ریکارڈنگ کی وجہ سے استعمال ہو گیا ہے۔"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"کوئی چینلز نہیں ملے"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"‏اسکین سے کوئی چینلز نہیں ملے۔ اپنے TV کے ایک TV سگنل ماخذ سے منسلک ہونے کی توثیق کریں۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں تو اس کا مقام یا سمت ایڈجسٹ کریں۔ بہترین نتائج کیلئے اسے اونچی جگہ اور کھڑکی کے پاس رکھیں اور دوبارہ اسکین کریں۔"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"‏اسکین سے کوئی چینلز نہیں ملے۔ USB ٹیونر کے پلگ ان ہونے اور TV سگنل ماخذ سے منسلک ہونے کی توثیق کریں۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں تو اس کا مقام یا سمت ایڈجسٹ کریں۔ بہترین نتائج کیلئے اسے اونچی جگہ اور کھڑکی کے پاس رکھیں اور دوبارہ اسکین کریں۔"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"‏اسکین سے کوئی چینلز نہیں ملے۔ توثیق کریں کہ نیٹ ورک ٹیونر آن ہے اور TV سگنل ماخذ سے منسلک ہے۔\n\nاگر وائرلیس نیٹ ورک کنکشن انٹینا استعمال کر رہے ہیں، تو اس کا مقام یا سمت ایڈجسٹ کریں۔ بہترین نتائج کیلئے، اسے اونچی جگہ اور کھڑکی کے قریب رکھیں اور دوبارہ اسکین کریں۔"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"دوبارہ اسکین کریں"</item>
     <item msgid="2092797862490235174">"ہو گیا"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"‏TV چینلز کے لیے اسکین کریں"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"‏TV ٹیونر سیٹ اپ"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"‏USB TV ٹیونر سیٹ اپ"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"‏USB TV ٹیونر غیر منسلک ہے۔"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"‏TV چینلز کے لیے اسکین کریں"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"‏TV ٹیونر سیٹ اپ"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"‏USB TV ٹیونر سیٹ اپ"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"‏نیٹ ورک TV ٹیونر سیٹ اپ"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"‏USB TV ٹیونر غیر منسلک ہے۔"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"نیٹ ورک ٹیونر غیر منسلک ہے۔"</string>
 </resources>
diff --git a/usbtuner-res/values-uz/strings.xml b/usbtuner-res/values-uz-rUZ/strings.xml
similarity index 74%
rename from usbtuner-res/values-uz/strings.xml
rename to usbtuner-res/values-uz-rUZ/strings.xml
index 9aefd57..2709dec 100644
--- a/usbtuner-res/values-uz/strings.xml
+++ b/usbtuner-res/values-uz-rUZ/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"TV-tyuner"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB TV-tyuner"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Yoqish"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"O‘chirib qo‘yish"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Tarmoq TV-tyuneri (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Iltimos, jarayon tugashini kuting"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Kanal manbasini tanlang"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Signal yo‘q"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"“<xliff:g id="CHANNEL_NAME">%s</xliff:g>” kanaliga sozlab bo‘lmadi"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Sozlab bo‘lmadi"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Tyunerning dasturiy ta’minoti yaqinda yangilandi. Kanallarni qaytadan qidiring."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Audioni yoqish uchun tizim ovozi sozlamalari orqali qamrovli ovozni yoqing"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Audioni ijro ettirib bo‘lmadi. Boshqa kanalni sinab ko‘ring."</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Tyunerni sozlash"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"TV-tyunerni sozlash"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB-tyunerni sozlash"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Tarmoq tyunerini sozlash"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Televizor signali manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, ko‘proq kanal topilishi uchun uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"USB-tyuner suqilgan hamda televizor signali manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, ko‘proq kanal topilishi uchun uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Tarmoq tyuneri yoqilgan hamda televizor signali manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, ko‘proq kanal topilishi uchun uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Davom etish"</item>
     <item msgid="727245208787621142">"Hozir emas"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Kanallar qaytadan sozlansinmi?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Buning natijasida TV-tyuner orqali topilgan kanallar o‘chirib tashlanadi va kanallar boshqatdan qidiriladi.\n\nTelevizor signal manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating hamda qaytadan qidiring."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Buning natijasida USB-tyuner orqali topilgan kanallar o‘chirib tashlanadi va kanallar boshqatdan qidiriladi.\n\nUSB-tyuner suqilgan hamda televizor signali manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating hamda qaytadan qidiring."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Buning natijasida tarmoq tyuneri orqali topilgan kanallar o‘chirib tashlanadi va kanallar boshqatdan qidiriladi.\n\nTarmoq tyuneri yoqilgan hamda televizor signali manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating hamda qaytadan qidiring."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Davom etish"</item>
     <item msgid="235450158666155406">"Bekor qilish"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"TV-tyunerni sozlash"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB-tyunerni sozlash"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Tarmoq tyuneri kanallarini sozlash"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Bu bir necha daqiqa vaqt olishi mumkin"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Tyunerdan vaqtinchalik foydalanib bo‘lmaydi yoki allaqachon yozib olishda foydalanilmoqda."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Hech qanday kanal topilmadi"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Qidiruv natijasida hech qanday kanal topilmadi. Televizor signal manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating hamda qaytadan qidiring."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Qidiruv natijasida hech qanday kanal topilmadi. USB-tyuner suqilgan hamda televizor signali manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating hamda qaytadan qidiring."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Qidiruv natijasida hech qanday kanal topilmadi. Tarmoq tyuneri yoqilgan hamda televizor signali manbasiga ulangan ekanligini tekshiring.\n\nAgar havo orqali to‘lqin tutuvchi antennadan foydalanayotgan bo‘lsangiz, uning joyi va yo‘nalishini sozlang. Eng yaxshi natijaga erishish uchun uni yuqoriroq va oynaga yaqin joyga o‘rnating hamda qaytadan qidiring."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Yana qidirish"</item>
     <item msgid="2092797862490235174">"Tayyor"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Telekanallarni qidiring"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"TV-tyunerni sozlash"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB TV-tyunerni sozlang"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB-tyuner o‘chirib qo‘yildi."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Telekanallarni qidiring"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"TV-tyunerni sozlash"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB TV-tyunerni sozlang"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Tarmoq TV-tyunerini sozlash"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB-tyuner o‘chirib qo‘yildi."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Tarmoq tyuneri uzib qo‘yildi."</string>
 </resources>
diff --git a/usbtuner-res/values-vi/strings.xml b/usbtuner-res/values-vi/strings.xml
index 605234e..6e6cef7 100644
--- a/usbtuner-res/values-vi/strings.xml
+++ b/usbtuner-res/values-vi/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Bộ dò TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Bộ dò TV USB"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Bật"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Tắt"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Bộ dò TV mạng (BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Vui lòng đợi để hoàn tất xử lý"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Chọn nguồn kênh của bạn"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Không có tín hiệu"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Dò tới <xliff:g id="CHANNEL_NAME">%s</xliff:g> không thành công"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Dò không thành công"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Phần mềm bộ dò đã được cập nhật gần đây. Vui lòng quét lại các kênh."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Bật tính năng âm thanh vòm trong cài đặt âm thanh hệ thống để bật âm thanh"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Không thể phát âm thanh. Vui lòng thử TV khác"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Thiết lập bộ dò kênh"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Thiết lập bộ dò TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Thiết lập bộ dò kênh USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Thiết lập bộ dò mạng"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Hãy xác minh rằng TV của bạn đã được kết nối với nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây thì bạn có thể cần phải điều chỉnh vị trí hoặc hướng của ăng-ten đó để nhận nhiều kênh nhất. Để có kết quả tốt nhất, hãy đặt ăng-ten lên cao và gần cửa sổ."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Xác minh rằng bộ dò USB đã được cắm và được kết nối với nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây, có thể bạn cần phải điều chỉnh vị trí hoặc hướng của ăng-ten đó để nhận được nhiều kênh nhất. Để có kết quả tốt nhất, hãy đặt ăng-ten lên cao và gần cửa sổ."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Hãy xác minh là bộ dò mạng đã được bật nguồn và kết nối với một nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây, hãy điều chỉnh vị trí hoặc hướng của ăng-ten để nhận hầu hết kênh. Để có kết quả tốt nhất, hãy đặt ăng-ten ở vị trí cao và gần cửa sổ."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Tiếp tục"</item>
     <item msgid="727245208787621142">"Không phải bây giờ"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Chạy lại quá trình thiết lập kênh?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Điều này sẽ xóa các kênh được tìm thấy khỏi bộ dò TV và quét các kênh mới lần nữa.\n\nHãy xác minh rằng TV của bạn đã được kết nối với nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây thì bạn có thể cần phải điều chỉnh vị trí hoặc hướng của ăng-ten đó để nhận nhiều kênh nhất. Để có kết quả tốt nhất, hãy đặt ăng-ten lên cao và gần cửa sổ."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Quá trình này sẽ xóa các kênh bộ dò USB đã tìm thấy và quét lại để tìm các kênh mới.\n\nHãy xác minh rằng bộ dò USB đã được cắm và kết nối với nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây, bạn có thể cần phải điều chỉnh vị trí hoặc hướng của ăng-ten đó để nhận được nhiều kênh nhất. Để có kết quả tốt nhất, hãy đặt ăng-ten lên cao và gần cửa sổ."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Điều này sẽ xóa các kênh được tìm thấy từ bộ dò mạng và quét các kênh mới một lần nữa.\n\nHãy xác minh là bộ dò mạng đã được bật nguồn và kết nối với một nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây, hãy điều chỉnh vị trí hoặc hướng của ăng-ten để nhận hầu hết kênh. Để có kết quả tốt nhất, hãy đặt ăng-ten ở vị trí cao và gần cửa sổ."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Tiếp tục"</item>
     <item msgid="235450158666155406">"Hủy"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Thiết lập bộ dò TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Thiết lập bộ dò kênh USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Thiết lập bộ do kênh mạng"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Quá trình này có thể mất vài phút"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Bộ dò tạm thời không có sẵn hoặc đã được sử dụng để ghi."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Không tìm thấy kênh nào"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Quá trình quét không tìm thấy bất kỳ kênh nào. Hãy xác minh rằng TV của bạn đã được kết nối với nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây, hãy điều chỉnh vị trí hoặc hướng của ăng-ten đó. Để có kết quả tốt nhất, hãy đặt ăng-ten lên cao và gần cửa sổ rồi quét lại."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Quá trình quét không tìm thấy bất kỳ kênh nào. Hãy xác minh rằng bộ dò USB đã được cắm và kết nối với nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây, hãy điều chỉnh vị trí hoặc hướng của ăng-ten đó. Để có kết quả tốt nhất, hãy đặt ăng-ten lên cao và gần cửa sổ rồi quét lại."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Quá trình quét không tìm thấy bất kỳ kênh nào. Hãy xác minh là bộ dò mạng đã được bật nguồn và kết nối với một nguồn tín hiệu TV.\n\nNếu sử dụng ăng-ten không dây, hãy điều chỉnh vị trí hoặc hướng của ăng-ten. Để có kết quả tốt nhất, hãy đặt ăng-ten ở vị trí cao và gần cửa sổ và quét lại."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Quét lại"</item>
     <item msgid="2092797862490235174">"Xong"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Quét tìm các kênh TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Thiết lập bộ dò TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Thiết lập bộ dò TV USB."</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Đã ngắt kết nối bộ điều chỉnh TV USB."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Quét tìm các kênh TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Thiết lập bộ dò TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Thiết lập bộ dò TV USB."</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Thiết lập bộ dò TV mạng"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Đã ngắt kết nối bộ dò truyền hình USB."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Đã ngắt kết nối bộ dò mạng."</string>
 </resources>
diff --git a/usbtuner-res/values-zh-rCN/strings.xml b/usbtuner-res/values-zh-rCN/strings.xml
index a4f6da2..cf2b477 100644
--- a/usbtuner-res/values-zh-rCN/strings.xml
+++ b/usbtuner-res/values-zh-rCN/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"电视调谐器"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB 电视调谐器"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"开启"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"关闭"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"网络电视调谐器(测试版)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"请耐心等待处理完毕"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"选择您的频道来源"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"无信号"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"无法调到<xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"无法调到相应频道"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"调谐器软件近期已更新。请重新扫描频道。"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"在系统声音设置中启用环绕声即可启用音频"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"无法播放音频,请试试其他电视频道"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"频道调谐器设置"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"电视调谐器设置"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB 频道调谐器设置"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"网络调谐器设置"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"请检查您的电视是否已连接到电视信号源。\n\n如果您使用的是无线电视,则可能需要调节天线的位置或方向,以便接收尽可能多的频道。要获得最佳效果,请将天线的位置调高并靠近窗户。"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"请检查 USB 调谐器是否已插好并连接到电视信号源。\n\n如果您使用的是无线电视,则可能需要调节天线的位置或方向,以便接收尽可能多的频道。要获得最佳效果,请将天线的位置调高并靠近窗户。"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"请检查网络调谐器是否已接通电源并连接到电视信号源。\n\n如果您使用的是无线电视,则可能需要调节天线的位置或方向,以便接收尽可能多的频道。要获得最佳效果,请将天线的位置调高并靠近窗户。"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"继续"</item>
     <item msgid="727245208787621142">"以后再说"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"要重新进行频道设置吗?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"此操作将移除通过电视调谐器找到的频道,并重新扫描新频道。\n\n请检查您的电视是否已连接到电视信号源。\n\n如果您使用的是无线电视,则可能需要调节天线的位置或方向,以便接收尽可能多的频道。要获得最佳效果,请将天线的位置调高并靠近窗户。"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"此操作将移除通过 USB 调谐器找到的频道,并重新扫描新频道。\n\n请检查 USB 调谐器是否已插好并连接到电视信号源。\n\n如果您使用的是无线电视,则可能需要调节天线的位置或方向,以便接收尽可能多的频道。要获得最佳效果,请将天线的位置调高并靠近窗户。"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"此操作将移除通过网络调谐器找到的频道,并重新扫描新频道。\n\n请检查网络调谐器是否已接通电源并连接到电视信号源。\n\n如果您使用的是无线电视,则可能需要调节天线的位置或方向,以便接收尽可能多的频道。要获得最佳效果,请将天线的位置调高并靠近窗户。"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"继续"</item>
     <item msgid="235450158666155406">"取消"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"电视调谐器设置"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB 频道调谐器设置"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"网络频道调谐器设置"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"此过程可能需要几分钟时间"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"调谐器暂时无法使用或已用于录制。"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"未找到任何频道"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"扫描后未找到任何频道。请检查您的电视是否已连接到电视信号源。\n\n如果您使用的是无线电视,请调节天线的位置或方向。要获得最佳效果,请将天线的位置调高并靠近窗户,然后再扫描一次。"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"扫描后未找到任何频道。请检查 USB 调谐器是否已插好并连接到电视信号源。\n\n如果您使用的是无线电视,请调节天线的位置或方向。要获得最佳效果,请将天线的位置调高并靠近窗户,然后再扫描一次。"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"扫描后未找到任何频道。请检查网络调谐器是否已接通电源并连接到电视信号源。\n\n如果您使用的是无线电视,请调节天线的位置或方向。要获得最佳效果,请将天线的位置调高并靠近窗户,然后再扫描一次。"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"重新扫描"</item>
     <item msgid="2092797862490235174">"完成"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"扫描电视频道"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"电视调谐器设置"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB 电视调谐器设置"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB 电视调谐器已断开连接。"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"扫描电视频道"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"电视调谐器设置"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB 电视调谐器设置"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"网络电视调谐器设置"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB 电视调谐器已断开连接。"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"网络调谐器已断开连接。"</string>
 </resources>
diff --git a/usbtuner-res/values-zh-rHK/strings.xml b/usbtuner-res/values-zh-rHK/strings.xml
index 6d40401..f2b8951 100644
--- a/usbtuner-res/values-zh-rHK/strings.xml
+++ b/usbtuner-res/values-zh-rHK/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"電視調諧器"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB 電視調諧器"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"開啟"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"關閉"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"網絡電視調諧器 (測試版)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"請等待系統完成處理程序"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"請選擇您的頻道來源"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"無訊號"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"無法調校至<xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"無法調校頻道"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"調諧器軟件最近已更新。請重新掃瞄頻道。"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"在系統音效設定中啟用環迴立體聲功能即可啟用音效"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"無法播放音效,請嘗試使用其他電視頻道"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"頻道調諧器設定"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"電視調諧器設定"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB 頻道調諧器設定"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"網絡調諧器設定"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"請確定電視已連接至電視訊號來源。\n\n如果您使用無線天線,可能需要調整天線的位置或方向,以接收最多頻道。您亦可將天線放在較高位置並靠近窗戶,以獲得最佳效果。"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"請確定 USB 調諧器已接駁並連接至電視訊號來源。\n\n如果您使用無線天線,可能需要調整天線的位置或方向,以接收最多頻道。您亦可以將天線放在較高位置並靠近窗戶,以獲取最佳效果。"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"請確定網絡調諧器已開啟電源,並連接至電視訊號來源。\n\n如果您使用無線天線,可能需要調整天線的位置或方向,以接收最多頻道。要取得最佳效果,請將天線放在較高位置並靠近窗戶,然後重新掃瞄。"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"繼續"</item>
     <item msgid="727245208787621142">"暫時不要"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"要重新設定頻道嗎?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"這項操作將移除電視調諧器找到的頻道,並重新掃瞄新的頻道。\n\n請確定電視已連接至電視訊號來源。\n\n如果您使用無線天線,可能需要調整天線的位置或方向,以接收最多頻道。您亦可將天線放在較高位置並靠近窗戶,以獲得最佳效果。"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"這項操作將移除 USB 調諧器找到的頻道,並會重新掃瞄新頻道。\n\n請確定 USB 調諧器已接駁並連接至電視訊號來源。\n\n如果您使用無線天線,可能需要調整天線的位置或方向,以接收最多頻道。您亦可將天線放在較高位置並靠近窗戶,以獲取最佳效果。"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"這項操作將移除網絡調諧器找到的頻道,並再次掃瞄新頻道。\n\n請確定網絡調諧器已開啟電源並連接至電視訊號來源。\n\n如果您使用無線天線,請調整天線的位置或方向。要取得最佳效果,請將天線放在較高位置並靠近窗戶,然後重新掃瞄。"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"繼續"</item>
     <item msgid="235450158666155406">"取消"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"電視調諧器設定"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB 頻道調諧器設定"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"網絡頻道調諧器設定"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"可能需時數分鐘"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"調諧器暫時無法使用,或已用於錄影。"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"找不到頻道"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"掃瞄後找不到頻道。請確定電視已連接至電視訊號來源。\n\n如果您使用無線天線,請調整天線的位置或方向。您亦可將天線放在較高位置並靠近窗戶,然後重新掃瞄,以獲得最佳效果。"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"掃瞄找不到頻道。請確定 USB 調諧器已接駁並連接至電視訊號來源。\n\n如果您使用無線天線,請調整天線的位置或方向。您亦可將天線放在較高位置並靠近窗戶,然後重新掃瞄,以獲取最佳效果。"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"掃瞄後找不到任何頻道。請確定網絡調諧器已開啟電源,並連接至電視訊號來源。\n\n如果您使用無線天線,請調整天線的位置或方向。要取得最佳效果,請將天線放在較高位置並靠近窗戶,然後重新掃瞄。"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"重新掃瞄"</item>
     <item msgid="2092797862490235174">"完成"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"掃瞄電視頻道"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"電視調諧器設定"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB 電視調諧器設定"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"已解除 USB 電視調諧器的連接。"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"掃瞄電視頻道"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"電視調諧器設定"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB 電視調諧器設定"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"網絡電視調諧器設定"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB 電視調諧器已中斷連線。"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"網絡調諧器已中斷連線。"</string>
 </resources>
diff --git a/usbtuner-res/values-zh-rTW/strings.xml b/usbtuner-res/values-zh-rTW/strings.xml
index 802d8b7..86624ef 100644
--- a/usbtuner-res/values-zh-rTW/strings.xml
+++ b/usbtuner-res/values-zh-rTW/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"電視調諧器"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"USB 電視調諧器"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"開啟"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"關閉"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"網路電視調諧器 (測試版)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"請等待處理程序完成"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"選取你的頻道來源"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"無訊號"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"無法轉到「<xliff:g id="CHANNEL_NAME">%s</xliff:g>」"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"無法轉台"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"調諧器軟體最近已更新。請重新掃描頻道。"</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"前往系統音效設定開啟環繞音效即可啟用音訊"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"無法播放音訊,請改用其他電視頻道"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"頻道調諧器設定"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"電視調諧器設定"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"USB 頻道調諧器設定"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"網路調諧器設定"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"請確認你的電視已連接到電視訊號來源。\n\n如果你使用無線電視天線,可能需要調整天線的位置和方向,以便接收最多頻道。為達最佳效果,請將天線放在靠近窗戶的較高位置。"</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"請確認 USB 調諧器已插入並連接到電視訊號來源。\n\n如果你使用無線電視天線,可能需要調整天線的位置和方向,以便接收最多頻道。為達最佳效果,請將天線放在靠近窗戶的較高位置。"</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"請確認你的網路調諧器已開啟電源,並連接到電視訊號來源。\n\n如果你使用無線電視天線,可能需要調整天線的位置和方向,以便接收最多頻道。為達最佳效果,請將天線放在靠近窗戶的較高位置。"</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"繼續"</item>
     <item msgid="727245208787621142">"暫時不要"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"要重新設定頻道嗎?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"這項動作將移除電視調諧器找到的頻道,並再次掃描新的頻道。\n\n請確認你的電視已連接到電視訊號來源。\n\n如果你使用無線電視天線,可能需要調整天線的位置和方向,以便接收最多頻道。為達最佳效果,請將天線放在靠近窗戶的較高位置。"</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"這項動作將移除 USB 調諧器找到的頻道,並再次掃描新的頻道。\n\n請確認 USB 調諧器已插入並連接到電視訊號來源。\n\n如果你使用無線電視天線,可能需要調整天線的位置和方向,以便接收最多頻道。為達最佳效果,請將天線放在靠近窗戶的較高位置。"</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"這個動作將移除網路調諧器找到的頻道,並再次掃描新的頻道。\n\n請確認你的網路調諧器已開啟電源,並連接到電視訊號來源。\n\n如果你使用無線電視天線,可能需要調整天線的位置和方向,以便接收最多頻道。為達最佳效果,請將天線放在靠近窗戶的較高位置。"</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"繼續"</item>
     <item msgid="235450158666155406">"取消"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"電視調諧器設定"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"USB 頻道調諧器設定"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"網路頻道調諧器設定"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"這可能需要幾分鐘的時間"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"調諧器暫時無法使用,或是已用於錄製。"</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"找不到任何頻道"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"掃描後並未發現任何頻道。請確認你的電視已連接到電視訊號來源。\n\n如果你使用無線電視天線,請調整天線的位置和方向。為達最佳效果,請將天線放在靠近窗戶的較高位置,然後再掃描一次。"</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"掃描後並未發現任何頻道。請確認 USB 調諧器已插入並連接到電視訊號來源。\n\n如果你使用無線電視天線,請調整天線的位置和方向。為達最佳效果,請將天線放在靠近窗戶的較高位置,然後再掃描一次。"</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"掃描後並未發現任何頻道。請確認你的網路調諧器已開啟電源,並連接到電視訊號來源。\n\n如果你使用無線電視天線,請調整天線的位置和方向。為達最佳效果,請將天線放在靠近窗戶的較高位置,然後再掃描一次。"</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"重新掃描"</item>
     <item msgid="2092797862490235174">"完成"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"掃描電視頻道"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"電視調諧器設定"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"USB 電視調諧器設定"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"USB 電視調諧器已中斷連結。"</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"掃描電視頻道"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"電視調諧器設定"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"USB 電視調諧器設定"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"網路電視調諧器設定"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"USB 電視調諧器已中斷連線。"</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"網路調諧器已中斷連線。"</string>
 </resources>
diff --git a/usbtuner-res/values-zu/strings.xml b/usbtuner-res/values-zu/strings.xml
index 905e9a1..fa8df8d 100644
--- a/usbtuner-res/values-zu/strings.xml
+++ b/usbtuner-res/values-zu/strings.xml
@@ -19,20 +19,18 @@
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="bt_app_name" msgid="5515382901862469770">"Ishuna ye-TV"</string>
     <string name="ut_app_name" msgid="8557698013780762454">"Ishuna ye-USB TV"</string>
-    <string name="ut_setup_on" msgid="7755608253387551795">"Vuliwe"</string>
-    <string name="ut_setup_off" msgid="1333878787059290524">"Valiwe"</string>
+    <string name="nt_app_name" msgid="4627006858832620833">"Ishuna yenethiwekhi ye-TV (i-BETA)"</string>
     <string name="ut_setup_cancel" msgid="5318292052302751909">"Sicela ulinde ukuze uqede ukucubungula"</string>
-    <string name="ut_select_channel_map" msgid="4831940000362338865">"Khetha umthombo wesiteshi sakho"</string>
-    <string name="ut_no_signal" msgid="7390099185275997984">"Ayikho isignali"</string>
-    <string name="ut_fail_to_tune" msgid="2964582177222053143">"Yehlulekile ukushunela ku-<xliff:g id="CHANNEL_NAME">%s</xliff:g>"</string>
-    <string name="ut_fail_to_tune_to_unknown_channel" msgid="7078953579048783762">"Yehlulekile ukushuna"</string>
     <string name="ut_rescan_needed" msgid="2273655435759849436">"Isofthiwe yeshuna ibuyekezwe kamuva. Sicela uphinde uskene iziteshi."</string>
     <string name="ut_surround_sound_disabled" msgid="6465044734143962900">"Nika amandla umsindo ozungezile kuzilungiselelo zomsindo wesistimu"</string>
+    <string name="audio_passthrough_not_supported" msgid="8766302073295760976">"Ayikwazi ukudlala umsindo. Sicela uzame enye i-TV"</string>
     <string name="ut_setup_breadcrumb" msgid="2810318605327367247">"Ukusethwa kweshuna yesiteshi"</string>
     <string name="bt_setup_new_title" msgid="8447554965697762891">"Ukusethwa kweshuna ye-TV"</string>
     <string name="ut_setup_new_title" msgid="2118880835101453405">"Ukusetha kweshuna yesiteshi se-USB"</string>
+    <string name="nt_setup_new_title" msgid="2996573474450060002">"Ukusethwa kweshuna yenethiwekhi"</string>
     <string name="bt_setup_new_description" msgid="256690722062003128">"Qinisekisa ukuthi i-TV yakho ixhunywe kumthombo wesignali ye-TV.\n\nUma usebenzisa i-antenna esemoyeni, kungenzeka ukuthi kumele ulungise ukubekwa noma ukubheka ukuze uthole iziteshi eziningi. Ukuze uthole imiphumela ehamba phambili, beka phezulu naseduze kwewindi."</string>
     <string name="ut_setup_new_description" msgid="2610122936163002137">"Qinisekisa ukuthi ishuna ye-USB ixhunyiwe futhi ixhumeke kumthombo wesignali ye-TV.\n\nUma usebenzisa i-antenna esemoyeni, kuzomele ulungise ukubekwa kwayo noma ukubheka kwayo ukuze uthole iziteshi eziningi. Ukuze uthole imiphumela ehamba phambili, yibeke phezulu eduze kwewindi."</string>
+    <string name="nt_setup_new_description" msgid="8315318180352515751">"Qinisekisa ukuthi ishuna yenethiwekhi ivuliwe yaphinde yaxhunywa kumthombo wesignali ye-TV.\n\nUma usebenzisa i-antenna esemoyeni, kungenzeka ukuthi kumele ulungise ukubekwa kwayo noma indawo ebhekiwe ukuze uthole iziteshi eziningi. Ukuze uthole imiphumela ehamba phambili, ibeke ngaphezulu naseduze kwewindi."</string>
   <string-array name="ut_setup_new_choices">
     <item msgid="8728069574888601683">"Qhubeka"</item>
     <item msgid="727245208787621142">"Hhayi manje"</item>
@@ -40,6 +38,7 @@
     <string name="bt_setup_again_title" msgid="884713873101099572">"Phinda uqalise ukusethwa kwesiteshi?"</string>
     <string name="bt_setup_again_description" msgid="1247792492948741337">"Lokhu kuzosusa iziteshi ezitholwe kusukela kushuna ye-TV kuphinde kuskenele iziteshi ezintsha.\n\nQinisekisa ukuthi i-TV yakho ixhunywe kumthombo wesignali ye-TV.\n\nUma usebenzisa i-antenna esemoyeni, kungenzeka ukuthi kumele ulungise ukubekwa noma ukubheka ukuze uthole iziteshi eziningi. Ukuze uthole imiphumela ehamba phambili, beka phezulu naseduze kwewindi."</string>
     <string name="ut_setup_again_description" msgid="7837706010887799255">"Lokhu kuzosusa iziteshi ezitholakele kusukela kushuna ye-USB kuphinde kuskenele iziteshi ezintsha futhi.\n\nQinisekisa ukuthi ishuna ye-USB ixhunyiwe futhi ixhumeke kumthombo wesignali ye-TV.\n\nUma usebenzisa i-antenna esemoyeni, kuzomele ulungise ukubekwa kwayo noma ukubheka kwayo ukuze uthole iziteshi eziningi. Ukuze uthole imiphumela ehamba phambili, yibeke ngaphezulu naseduze kwewindi."</string>
+    <string name="nt_setup_again_description" msgid="681642895365018072">"Lokhu kuzosusa iziteshi ezitholakele kusukela kushuna yenethiwekhi kuphinde kuskenele iziteshi ezintsha futhi.\n\nQinisekisa ukuthi ishuna yenethiwekhi ixhunyiwe futhi ixhumeke kumthombo wesignali ye-TV.\n\nUma usebenzisa i-antenna esemoyeni, kuzomele ulungise ukubekwa kwayo noma ukubheka kwayo ukuze uthole iziteshi eziningi. Ukuze uthole imiphumela ehamba phambili, yibeke ngaphezulu naseduze kwewindi."</string>
   <string-array name="ut_setup_again_choices">
     <item msgid="2557527790311851317">"Qhubeka"</item>
     <item msgid="235450158666155406">"Khansela"</item>
@@ -54,6 +53,7 @@
   </string-array>
     <string name="bt_channel_scan" msgid="3291924771702347469">"Ukusethwa kweshuna ye-TV"</string>
     <string name="ut_channel_scan" msgid="6100090671500464604">"Ukusetha kweshuna yesiteshi se-USB"</string>
+    <string name="nt_channel_scan" msgid="30206992732534178">"Ukusethwa kweshuna yesiteshi senethiwekhi"</string>
     <string name="ut_channel_scan_time" msgid="1844845425359642393">"Lokhu kungathatha amaminithi athile"</string>
     <string name="ut_channel_scan_tuner_unavailable" msgid="3135723754380409658">"Ishuna okwamanje ayitholakali noma isivele isetshenziswa ngokurekhodwa."</string>
     <plurals name="ut_channel_scan_message" formatted="false" msgid="3131606783282632056">
@@ -76,12 +76,15 @@
     <string name="ut_result_not_found_title" msgid="4649533929056795595">"Azikho iziteshi ezitholiwe"</string>
     <string name="bt_result_not_found_description" msgid="7378208337325024042">"Ukuskena akuzange kuthole iziteshi. Qinisekisa ukuthi i-TV yakho ixhumeke kumthombo wesignali we-TV.\n\nUma usebenzisa i-antenna esemoyeni, kungenzeka ukuthi kumele ulungise ukubekwa noma ukubheka ukuze uthole iziteshi eziningi. Ukuze uthole imiphumela ehamba phambili, beka phezulu naseduze kwewindi."</string>
     <string name="ut_result_not_found_description" msgid="1080746285957681414">"Iskena asizange sithole noma yiziphi iziteshi. Qinisekisa ukuthi ishuna ye-USB ixhunyiwe futhi ixhumeke kumthombo wesignali ye-TV.\n\nUma usebenzisa i-antenna esemoyeni, lungisa ukubekwa kwayo noma ukuma kwayo. Ukuze uthole imiphumela ehamba phambili, yibeke phezulu naseduze kwewindi uphinde uskene."</string>
+    <string name="nt_result_not_found_description" msgid="2177919867285510855">"Iskena asizange sithole noma iziphi iziteshi. Qinisekisa ukuthi ishuna ye-USB ixhunyiwe futhi ixhumeke kumthombo wesignali ye-TV.\n\nUma usebenzisa i-antenna esemoyeni, lungisa ukubekwa kwayo noma ukuma kwayo. Ukuze uthole imiphumela ehamba phambili, yibeke phezulu naseduze kwewindi uphinde uskene."</string>
   <string-array name="ut_result_not_found_choices">
     <item msgid="5436884968471542030">"Skena futhi"</item>
     <item msgid="2092797862490235174">"Kwenziwe"</item>
   </string-array>
-    <string name="ut_setup_recommendation_card_focused_title" msgid="7434151993964505386">"Skenela iziteshi ze-TV"</string>
-    <string name="bt_setup_recommendation_card_title" msgid="1026906771141769829">"Ukusethwa kweshuna ye-TV"</string>
-    <string name="ut_setup_recommendation_card_title" msgid="1093869817128338226">"Ukusetha kweshuna ye-USB TV"</string>
-    <string name="msg_usb_device_detached" msgid="5123930566630230724">"Isishuni se-USB TV sinqanyuliwe."</string>
+    <string name="ut_setup_notification_content_title" msgid="3439301313253273422">"Skenela iziteshi ze-TV"</string>
+    <string name="bt_setup_notification_content_text" msgid="7578820978070596694">"Ukusethwa kweshuna ye-TV"</string>
+    <string name="ut_setup_notification_content_text" msgid="1656697878628557384">"Ukusetha kweshuna ye-USB TV"</string>
+    <string name="nt_setup_notification_content_text" msgid="1186152789699583895">"Ukusethwa kweshuna yenethiwekhi ye-TV"</string>
+    <string name="msg_usb_tuner_disconnected" msgid="1206606328815245830">"Ishuna ye-USB TV inqanyuliwe."</string>
+    <string name="msg_network_tuner_disconnected" msgid="7103193099674978964">"Ishuna yenethiwekhi inqanyuliwe."</string>
 </resources>
diff --git a/usbtuner-res/values/colors.xml b/usbtuner-res/values/colors.xml
index bbcc431..873ecc8 100644
--- a/usbtuner-res/values/colors.xml
+++ b/usbtuner-res/values/colors.xml
@@ -16,15 +16,9 @@
   -->
 
 <resources>
-    <color name="ut_guidedstep_background">#01579B</color>
-    <color name="ut_guidance_title_text">#EEEEEE</color>
-    <color name="ut_guidance_breadcrumb_text">#EEEEEE</color>
-    <color name="ut_guidance_description_text">#B3EEEEEE</color>
-    <color name="ut_guidedactions_title_text">#EEEEEE</color>
     <color name="ut_scan_title_text">#EEEEEE</color>
     <color name="ut_scan_description_text">#B3EEEEEE</color>
     <color name="ut_scan_progress">#EEEEEE</color>
     <color name="ut_scan_progress_background">#26EEEEEE</color>
     <color name="ut_scan_button_text">#EEEEEE</color>
-    <color name="ut_scan_channellist_background">#26EEEEEE</color>
 </resources>
\ No newline at end of file
diff --git a/usbtuner-res/values/dimens.xml b/usbtuner-res/values/dimens.xml
index 0a09b06..1fe39f6 100644
--- a/usbtuner-res/values/dimens.xml
+++ b/usbtuner-res/values/dimens.xml
@@ -16,41 +16,7 @@
   -->
 
 <resources>
-    <!-- Default screen margins, per the Android Design guidelines. -->
-    <dimen name="ut_activity_horizontal_margin">16dp</dimen>
-    <dimen name="ut_activity_vertical_margin">16dp</dimen>
-
-    <dimen name="ut_guidance_section_width">592dp</dimen>
-    <dimen name="ut_guidedactions_section_width">368dp</dimen>
-
-    <dimen name="ut_guidedstep_entry_slide_from">100dp</dimen>
-    <dimen name="ut_guidedstep_exit_slide_to">-100dp</dimen>
-
-    <dimen name="ut_guidance_padding_start">56dp</dimen>
-    <dimen name="ut_guidance_padding_end">32dp</dimen>
-    <dimen name="ut_guidance_padding_top">27dp</dimen>
-    <dimen name="ut_guidance_anchor_height">156dp</dimen>
-
-    <dimen name="ut_guidance_title_text_size">34sp</dimen>
-    <dimen name="ut_guidance_breadcrumb_text_size">14sp</dimen>
-    <dimen name="ut_guidance_description_text_size">14sp</dimen>
-    <dimen name="ut_guidance_description_margin_top">8dp</dimen>
-
-    <dimen name="ut_guidedactions_padding_start">24dp</dimen>
-    <dimen name="ut_guidedactions_padding_end">40dp</dimen>
-    <dimen name="ut_guidedactions_padding_top">27dp</dimen>
-    <dimen name="ut_guidedactions_padding_bottom">48dp</dimen>
-    <dimen name="ut_guidedactions_anchor_height">163dp</dimen>
-    <dimen name="ut_guidedactions_selector_height">48dp</dimen>
-
-    <dimen name="ut_guidedactions_item_height">48dp</dimen>
-    <dimen name="ut_guidedactions_item_padding_start">16dp</dimen>
-    <dimen name="ut_guidedactions_item_padding_end">16dp</dimen>
-    <dimen name="ut_guidedactions_item_padding_top">14dp</dimen>
-    <dimen name="ut_guidedactions_item_padding_bottom">15dp</dimen>
-
     <dimen name="ut_scan_icon_width">80dp</dimen>
-    <dimen name="ut_scan_icon_height">80dp</dimen>
     <dimen name="ut_scan_icon_margin_right">24dp</dimen>
 
     <dimen name="ut_scan_title_text_size">34sp</dimen>
diff --git a/usbtuner-res/values/integers.xml b/usbtuner-res/values/integers.xml
index 21b438e..65d20c6 100644
--- a/usbtuner-res/values/integers.xml
+++ b/usbtuner-res/values/integers.xml
@@ -16,10 +16,5 @@
   -->
 
 <resources>
-    <integer name="ut_guidance_title_max_lines">2</integer>
-    <integer name="ut_guidance_description_max_lines">10</integer>
-    <integer name="ut_guidedactions_vertical_spcae">8</integer>
     <integer name="ut_scan_title_max_lines">2</integer>
-    <integer name="ut_entry_anim_duration">300</integer>
-    <integer name="ut_exit_anim_duration">300</integer>
 </resources>
\ No newline at end of file
diff --git a/usbtuner-res/values/strings.xml b/usbtuner-res/values/strings.xml
index e3a8586..dd393c3 100644
--- a/usbtuner-res/values/strings.xml
+++ b/usbtuner-res/values/strings.xml
@@ -18,26 +18,15 @@
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <!-- Name of this application. It appears in TV app UI, as one of available TV inputs. -->
     <string name="bt_app_name">TV Tuner</string>
-    <!-- Name of this application when one uses USB tuner. It appears in TV app UI, as one of
+    <!-- Name of this application when one uses USB tuners. It appears in TV app UI, as one of
          available TV inputs. -->
     <string name="ut_app_name">USB TV Tuner</string>
-    <!-- Title for an action which turns a feature on [CHAR LIMIT=30] -->
-    <string name="ut_setup_on">On</string>
-    <!-- Title for an action which turns a feature off [CHAR LIMIT=30] -->
-    <string name="ut_setup_off">Off</string>
+    <!-- Name of this application when one uses network tuners. It appears in TV app UI, as one of
+         available TV inputs. -->
+    <string name="nt_app_name">Network TV Tuner (BETA)</string>
     <!-- Message shown when the scanning process is being canceled by a user and the scanning
          process needs the time to wait to finish the processing -->
     <string name="ut_setup_cancel">Please wait to finish processing</string>
-    <!-- Message that asks a user to select the type of signal to be used for input among
-         the choices like terrestrial, cable, or satellite -->
-    <string name="ut_select_channel_map">Select your channel source</string>
-    <!-- Message that indicates TV input signal is lost due to physical disconnection or bad
-         reception -->
-    <string name="ut_no_signal">No Signal</string>
-    <!-- Message that says TV failed to change to a channel (or tune) -->
-    <string name="ut_fail_to_tune">Failed to tune to <xliff:g id="channel_name">%s</xliff:g></string>
-    <!-- Message that says TV failed to change(or tune) to a channel which has no title -->
-    <string name="ut_fail_to_tune_to_unknown_channel">Failed to tune</string>
     <!-- Message shown when the scanned channels became invalid due to incompatible changes
          found across application versions, hence a user is required to rescan the channels -->
     <string name="ut_rescan_needed">Tuner software has been recently updated. Please re-scan the
@@ -45,12 +34,16 @@
     <!-- Message that says audio of the current channel is not available due to surround sound
          of TV device disabled -->
     <string name="ut_surround_sound_disabled">Enable surround sound in system sound settings to enable audio</string>
+    <!-- Message that says audio of the current channel is not available due to AC3 passthrough is not usable -->
+    <string name="audio_passthrough_not_supported">Cannot play audio. Please try another TV</string>
     <!-- Usb Tuner setup common UI breadcrumb -->
     <string name="ut_setup_breadcrumb">Channel tuner setup</string>
     <!-- Title for TV Tuner main setup menu when no channel exists -->
     <string name="bt_setup_new_title">TV Tuner setup</string>
     <!-- Title for USB tuner main setup menu when no channel exists -->
     <string name="ut_setup_new_title">USB channel tuner setup</string>
+    <!-- Title for network tuner main setup menu when no channel exists -->
+    <string name="nt_setup_new_title">Network tuner setup</string>
     <!-- Description for TV tuner main setup menu when no channel exists -->
     <string name="bt_setup_new_description">Verify your TV is connected to a TV signal
         source.\n\nIf using an over-the-air antenna, you may need to adjust its placement or
@@ -61,6 +54,11 @@
         to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its
         placement or direction to receive the most channels. For best results,
         place it high and near a window.</string>
+    <!-- Description for network tuner main setup menu when no channel exists -->
+    <string name="nt_setup_new_description">Verify the network tuner is powered on and connected
+        to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its
+        placement or direction to receive the most channels. For best results,
+        place it high and near a window.</string>
     <!-- Menu items for USB tuner main setup menu when no channel exists -->
     <string-array name="ut_setup_new_choices">
         <!-- Continue setup -->
@@ -82,6 +80,12 @@
         to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust its
         placement or direction to receive the most channels. For best results, place it high and
         near a window.</string>
+    <!-- Description for network tuner main setup menu when channel exists already -->
+    <string name="nt_setup_again_description">This will remove the channels found from the network
+        tuner and scan for new channels again.\n\nVerify the network tuner is powered on and
+        connected to a TV signal source.\n\nIf using an over-the-air antenna, you may need to adjust
+        its placement or direction to receive the most channels. For best results, place it high and
+        near a window.</string>
     <!-- Menu items for USB tuner main setup menu when channel exists already -->
     <string-array name="ut_setup_again_choices">
         <!-- Continue setup -->
@@ -109,6 +113,8 @@
     <string name="bt_channel_scan">TV tuner setup</string>
     <!-- Title for channel scanning menu. Use this title with USB tuners -->
     <string name="ut_channel_scan">USB channel tuner setup</string>
+    <!-- Title for channel scanning menu. Use this title with network tuners -->
+    <string name="nt_channel_scan">Network channel tuner setup</string>
     <!-- Message that says channel is not yet scanned during channel scanning process -->
     <string name="ut_channel_scan_time">This may take several minutes</string>
     <!-- Message that says Tuner is not available -->
@@ -145,29 +151,41 @@
         your TV is connected to a TV signal source.\n\nIf using an over-the-air antenna, adjust
         its placement or direction. For best results, place it high and near a window and scan
         again.</string>
-    <!-- Description for channel scanning result menu when no channel was found -->
+    <!-- Description for channel scanning result menu when no channel was found with USB tuners-->
     <string name="ut_result_not_found_description">The scan did not find any channels. Verify the
         USB tuner is plugged in and connected to a TV signal source.\n\nIf using an over-the-air
         antenna, adjust its placement or direction. For best results, place it high and near a
         window and scan again.</string>
+    <!-- Description for channel scanning result menu when no channel was found with network
+         tuners -->
+    <string name="nt_result_not_found_description">The scan did not find any channels. Verify the
+        network tuner is powered on and connected to a TV signal source.\n\nIf using an over-the-air
+        antenna, adjust its placement or direction. For best results, place it high and near a
+        window and scan again.</string>
     <!-- Menu items for channel scanning result menu when no channel was found -->
     <string-array name="ut_result_not_found_choices">
         <item>Scan again</item>
         <item>Done</item>
     </string-array>
 
-    <!-- Recommendation card of USB channel tuner setup strings. -->
-    <!-- Content title of the recommendation card to launch the setup application of
-         USB tuner TV input for scanning channels. This text is shown only when the card is
-         focused. -->
-    <string name="ut_setup_recommendation_card_focused_title">Scan for TV channels</string>
-    <!-- Content text and info of the recommendation card to launch the setup application of
-         built-in tuner TV input for scanning channels. -->
-    <string name="bt_setup_recommendation_card_title">TV Tuner setup</string>
-    <!-- Content text and info of the recommendation card to launch the setup application of
+    <!-- Notification of USB channel tuner setup strings. -->
+    <!-- Name of notification channel which is for tuner setup. -->
+    <string name="ut_setup_notification_channel_name" translatable="false">USB tuner set up</string>
+    <!-- Content title of the notification to launch the setup application of
          USB tuner TV input for scanning channels. -->
-    <string name="ut_setup_recommendation_card_title">USB TV Tuner setup</string>
+    <string name="ut_setup_notification_content_title">Scan for TV channels</string>
+    <!-- Content text and info of the notification to launch the setup application of
+         built-in tuner TV input for scanning channels. -->
+    <string name="bt_setup_notification_content_text">TV Tuner setup</string>
+    <!-- Content text and info of the notification to launch the setup application of
+         USB tuner TV input for scanning channels. -->
+    <string name="ut_setup_notification_content_text">USB TV Tuner setup</string>
+    <!-- Content text and info of the notification to launch the setup application of
+         network tuner TV input for scanning channels. -->
+    <string name="nt_setup_notification_content_text">Network TV Tuner setup</string>
 
-    <!-- Message when usb tuner device is unplugged. [CHAR LIMIT=NONE] -->
-    <string name="msg_usb_device_detached">USB TV tuner disconnected.</string>
+    <!-- Message when USB tuner device is unplugged or disconnected. [CHAR LIMIT=NONE] -->
+    <string name="msg_usb_tuner_disconnected">USB TV tuner disconnected.</string>
+    <!-- Message when Network tuner device is unplugged or disconnected. [CHAR LIMIT=NONE] -->
+    <string name="msg_network_tuner_disconnected">Network tuner disconnected.</string>
 </resources>
diff --git a/usbtuner-res/values/styles.xml b/usbtuner-res/values/styles.xml
deleted file mode 100644
index c79319b..0000000
--- a/usbtuner-res/values/styles.xml
+++ /dev/null
@@ -1,120 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ 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.
-  -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
-    <style name="ut_guidance_anchor">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">@dimen/ut_guidance_anchor_height</item>
-    </style>
-    <style name="ut_guidance_container">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:background">@null</item>
-        <item name="android:clipToPadding">false</item>
-        <item name="android:clipChildren">false</item>
-    </style>
-    <style name="ut_guidance_title">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_alignWithParentIfMissing">true</item>
-        <item name="android:layout_below">@id/guidance_anchor_space</item>
-        <item name="android:ellipsize">end</item>
-        <item name="android:fontFamily">sans-serif-light</item>
-        <item name="android:maxLines">@integer/ut_guidance_title_max_lines</item>
-        <item name="android:textColor">@color/ut_guidance_title_text</item>
-        <item name="android:textSize">@dimen/ut_guidance_title_text_size</item>
-    </style>
-    <style name="ut_guidance_breadcrumb">
-        <item name="android:layout_above">@id/guidance_title</item>
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_alignWithParentIfMissing">true</item>
-        <item name="android:ellipsize">end</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
-        <item name="android:singleLine">true</item>
-        <item name="android:textColor">@color/ut_guidance_breadcrumb_text</item>
-        <item name="android:textSize">@dimen/ut_guidance_breadcrumb_text_size</item>
-    </style>
-    <style name="ut_guidance_desc">
-        <item name="android:layout_below">@id/guidance_title</item>
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_marginTop">@dimen/ut_guidance_description_margin_top</item>
-        <item name="android:layout_alignWithParentIfMissing">true</item>
-        <item name="android:ellipsize">end</item>
-        <item name="android:fontFamily">sans-serif</item>
-        <item name="android:maxLines">@integer/ut_guidance_description_max_lines</item>
-        <item name="android:textColor">@color/ut_guidance_description_text</item>
-        <item name="android:textSize">@dimen/ut_guidance_description_text_size</item>
-    </style>
-    <style name="ut_guidedactions_container">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:background">@null</item>
-        <item name="android:clipToPadding">false</item>
-        <item name="android:clipChildren">false</item>
-    </style>
-    <style name="ut_guidedactions_anchor">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">@dimen/ut_guidedactions_anchor_height</item>
-    </style>
-    <style name="ut_guidedactions_null_selector">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">@dimen/ut_guidedactions_selector_height</item>
-        <item name="android:layout_below">@id/guidedactions_anchor_space</item>
-        <item name="android:background">@null</item>
-    </style>
-    <style name="ut_guidedactions_list">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">match_parent</item>
-        <item name="android:layout_below">@id/guidedactions_anchor_space</item>
-        <item name="android:background">@null</item>
-        <item name="android:clipToPadding">false</item>
-        <item name="android:clipChildren">false</item>
-        <item name="android:focusable">true</item>
-    </style>
-    <style name="ut_guidedactions_item_container">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">@dimen/ut_guidedactions_item_height</item>
-        <item name="android:background">@drawable/ut_selector_background</item>
-        <item name="android:focusable">true</item>
-        <item name="android:paddingStart">@dimen/ut_guidedactions_item_padding_start</item>
-        <item name="android:paddingEnd">@dimen/ut_guidedactions_item_padding_end</item>
-        <item name="android:paddingTop">@dimen/ut_guidedactions_item_padding_top</item>
-        <item name="android:paddingBottom">@dimen/ut_guidedactions_item_padding_bottom</item>
-    </style>
-    <style name="ut_guidedactions_item_checkmark">
-        <item name="android:layout_width">@dimen/lb_guidedactions_item_checkmark_diameter</item>
-        <item name="android:layout_height">@dimen/lb_guidedactions_item_checkmark_diameter</item>
-        <item name="android:visibility">gone</item>
-    </style>
-    <style name="ut_guidedactions_item_title">
-        <item name="android:layout_width">match_parent</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:ellipsize">end</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
-        <item name="android:singleLine">true</item>
-        <item name="android:textColor">@color/ut_guidedactions_title_text</item>
-        <item name="android:textSize">14sp</item>
-        <item name="android:background">@null</item>
-    </style>
-    <style name="ut_guidedactions_item_chevron">
-        <item name="android:layout_width">wrap_content</item>
-        <item name="android:layout_height">wrap_content</item>
-        <item name="android:visibility">gone</item>
-    </style>
-</resources>
diff --git a/version.mk b/version.mk
index f63f583..6886dc0 100644
--- a/version.mk
+++ b/version.mk
@@ -48,13 +48,13 @@
 
 base_version_major := 1
 # Change this for each branch
-base_version_minor := 11
+base_version_minor := 15
 
 # code_version_major will overflow at 22
 code_version_major := $(shell echo $$(($(base_version_major)+3)))
 
 # x86 and arm sometimes don't match.
-code_version_build := 011
+code_version_build := 007
 #####################################################
 #####################################################
 # Collect automatic version code parameters
@@ -96,7 +96,7 @@
 ifdef TARGET_BUILD_APPS
 ifneq "" "$(filter eng.%,$(BUILD_NUMBER))"
     git_hash := $(shell git --git-dir $(LOCAL_PATH)/.git log -n 1 --pretty=format:%h)
-    date_string := $(shell date +%m%d%y_%H%M%S)
+    date_string := $(shell date +%Y-%m-%d)
     version_name_package := $(base_version_major).$(base_version_minor).$(code_version_build) (eng.$(USER).$(git_hash).$(date_string)-$(base_version_arch)$(base_version_density))
 else
     version_name_package := $(base_version_major).$(base_version_minor).$(code_version_build) ($(BUILD_NUMBER)-$(base_version_arch)$(base_version_density))